众所周知,Java 是一门需要编译的语言,JVM 读取并运行的是编译后的 .class 字节码文件。 那么像 IDEA 之类的 IDE 是怎么做到在 Debug 时随心所欲地计算或者改变变量的呢?事实 上这一过程不需要重新编译再执行,而是通过 Java 动态字节码技术直接修改字节码文件, 再通过相关接口加载到 JVM 中,实现运行时的代码修改。

实现动态字节码的技术有很多种,BCELJavassistASM、CGLib 等,各有自己的优势。

Instrument

字节码是修改完了,可是 JVM 在执行时会使用自己的类加载器加载字节码文件,加载后并 不会理会我们做出的修改,要想实现对现有类的修改,需要用到的 instrument 库。

instrument 是 JVM 提供的一个可以修改已加载类文件的类库。1.6 以前,instrument 只能 在 JVM 刚启动开始加载类时生效,之后 instrument 支持了在运行时对类定义的修改。

要使用 instrument 的类修改功能,我们需要实现它的 ClassFileTransformer 接口定义一 个类文件转换器。它唯一的一个 transform() 方法会在类文件被加载时调用,在 transform 方法里,我们可以对传入的二进制字节码进行改写或替换,生成新的字节码数组 后返回,JVM 会使用 transform 方法返回的字节码数据进行类的加载。

JVMTI

JVMTI(JVM Tool Interface)是 JVM 提供的一个非常强大的对 JVM 操作的工具接口,通 过这个接口,我们可以实现对 JVM 多种组件的操作,从 JVMTM Tool Interface 这里我们 认识到 JVM TI 的强大,它包括了对虚拟机堆内存、类、线程等各个方面的管理接口。

JVMTI 通过事件机制,通过接口注册各种事件勾子,在 JVM 事件触发时同时触发预定义的 勾子,以实现对各个 JVM 事件的感知和反应。