2026年6月14日

技术教程 如何在FabricMC环境下自动为MinecraftClient和MinecraftServer运行任务启用DCEVM和Mixin热交换

作者 TheWhiteDog9487

事情是这样的。

众所周知,一般JDK的运行时代码热交换是有所限制的,不是什么东西都能热交换。

你说热交换是什么?比如我有一个函数a(),我现在已经开始了调试,但是我突然想把a的内部实现改一下。当我把源码改完点击热交换按钮,等了一会修改后的代码直接应用到了正在被调试器调试的进程内,这个过程中目标进程没有重启,这就是代码热交换。

关于这一点,Fabric Docs上也是写了的:

在 IntelliJ IDEA 中启动游戏 | Fabric 文档

不光如此,常规情况下Mixin注入的代码是无法被热交换的:

在 IntelliJ IDEA 中启动游戏 | Fabric 文档

其实我以前对搞这个增强热交换是挺无所谓的,直到我几天前真的去试用了一下:

TheWhiteDog9487的动态 – 哔哩哔哩

因此我去Fabric Loom的GitHub仓库开了个Feature Request,然后直接被close as not planned踹了回来:

[Feature Request] If using JetBrainsRuntime or other JVM that supports DCEVM, automatically add the JVM parameter `-XX:+AllowEnhancedClassRedefinition` to the generated IDE run tasks. · Issue #1574 · FabricMC/fabric-loom
TheWhiteDog9487的动态 – 哔哩哔哩

意思就是Fabric的维护者认为这不是Loom该负责的事情,所以不予采纳

完全可以理解,但是我这个人就这性格,别人不干我偏要干

所以,当当当当

afterEvaluate {
	val MixinJarPath = configurations.loaderLibraries.get().resolvedConfiguration
		.resolvedArtifacts
		.find { it.moduleVersion.id.group == "net.fabricmc" && it.moduleVersion.id.name == "sponge-mixin" }!!
		.file
	val IsSupportDceVM = Paths.get(System.getProperty("java.home"))
		.resolve("bin")
		.resolve("java")
		.toFile()
		.let {
			val ReturnCode = ProcessBuilder(it.absolutePath, "-XX:+AllowEnhancedClassRedefinition", "-version")
				.start()
				.waitFor()
			return@let ReturnCode == 0 }
	loom.runs.named("client") {
		vmArgs.add("-javaagent:${MixinJarPath.absolutePath}")
		if (IsSupportDceVM == true) vmArgs.add("-XX:+AllowEnhancedClassRedefinition") }
	loom.runs.named("server") {
		vmArgs.add("-javaagent:${MixinJarPath.absolutePath}")
		if (IsSupportDceVM == true) vmArgs.add("-XX:+AllowEnhancedClassRedefinition") } }

直接拿去用吧,这个调好的片段我以WTFPL授权出去,都哥们随便用

你需要把它添加到build.gradle.kts的顶级作用域内,也就是和 plugins{} dependencies{} loom{} 这些家伙平级的位置,不需要把它放到任何一个配置块之内。

然后,建议关闭IDEA,删除.idea文件夹,然后重新导入项目

哦还有,DceVM是否会生效取决于你项目的Gradle JDK而不是项目JDK!
Gradle JDK和项目JDK是分开的,有可能不一样!
如果你的JAVA_HOME变量指示的是一般的JDK,那你需要在 构建,执行,部署 -> 构建工具 -> Gradle 里切换Gradle JVM,然后删除Minecraft ClientMinecraft Server这两个任务,重新运行Gradle同步或者运行ideaSyncTask这个任务