Learn · concepts

什么是 ASM(Java 字节码)?库详解

ASM 是一個在執行時讀取和寫入 JVM 字節碼的 Java 庫。以下是其功能、工作原理以及為什麼 Minecraft 模組依賴它的原因.

TRtrolPublished 1 min read

什么是 Minecraft 模组开发中的 ASM?

ASM 是一个 Java 库,用于读取、修改和写入 JVM 字节码。它直接处理编译后的 .class 文件,而不是源代码,因此可以在不重新编译的情况下检查或重写类。Minecraft 模组依赖于它,因为它允许它们在游戏加载时修补游戏,即使游戏已经编译完成。

为什么存在字节码修补

Minecraft 游戏以编译后的字节码形式发布,而不是源代码。这意味着模组作者无法修改源代码并重新编译整个游戏:源代码不存在。修补你未拥有的代码的唯一方法是在字节码级别进行操作,即 Java 虚拟机实际运行的指令集。ASM 是完成这项工作的实用工具。

ASM 的工作原理

ASM 将编译后的类转换为程序可以编辑的内容。一个 .class 文件仅仅是字节码,即 Java 虚拟机运行的指令。ASM 解析这些字节码,将方法和字段交给你,并允许你添加、删除或更改指令。然后,它将一个新的有效类写回。

纯 Java 本身无法做到这一点。编译器将你的源代码编译成字节码一次,之后字节码就被固定了。ASM 在字节码级别进行操作,这低于你通常编写的源代码层。

访问者模式和树 API

ASM 读取一个类,使用 ClassReader,并写入一个类,使用 ClassWriter。 在两者之间,你的代码会访问类的各个部分并决定要进行哪些更改。 有两种方法:

访问者模式 逐个元素地流过类。 这种方法速度快且内存占用少,因为它从不持有整个类。 树模式 将类加载到你可以自由行走和编辑的对象中,这对于较大的更改来说更容易理解,但会占用更多内存。

方法工作方式适用场景
访问者 API流式读取类事件小而快速的编辑,内存占用低
树 API构建类的可编辑对象模型更大或更复杂的重写

为什么 Minecraft 模组使用 ASM

模组需要更改他们没有编写且无法重新编译的游戏代码。 游戏以编译后的类形式发布,因此唯一的入口点是字节码级别,而 ASM 正是提供了这一点。 模组可以在游戏方法中注入钩子,重定向调用或添加字段,所有这些都在启动时完成。

大多数模组制作者不会直接调用 ASM。 他们使用 Mixin,这是一个位于 ASM 之上的高级框架,可以将简单的注释转换为底层的字节码编辑。 你编写一个小的 Java 类来描述更改,框架会为你处理 ASM 的底层工作。 Fabric 模组尤其依赖于此链.

当你需要直接接触 ASM 时

作为模组作者,你很少会直接编写原始 ASM 代码。它通常出现在工具需要比注释所能表达的更多控制权时,例如加载器、混淆器或重写整个类的补丁程序。对于日常模组来说,顶层的注释层就足够了,而且出错的可能性要小得多.

常见问题