JVM 源码分析之 javaagent 原理完全解读
javaagent 的主要功能如下:
- 可以在加载 class 文件之前做拦截,对字节码做修改
- 可以在运行期对已加载类的字节码做变更,但是这种情况下会有很多的限制,后面会详细说
- 还有其他一些小众的功能
- 获取所有已经加载过的类
- 获取所有已经初始化过的类(执行过 clinit 方法,是上面的一个子集)
- 获取某个对象的大小
- 将某个 jar 加入到 bootstrap classpath 里作为高优先级被 bootstrapClassloader 加载
- 将某个 jar 加入到 classpath 里供 AppClassloard 去加载
- 设置某些 native 方法的前缀,主要在查找 native 方法的时候做规则匹配
JVMTI 全称 JVM Tool Interface,是 JVM 暴露出来的一些供用户扩展的接口集合。JVMTI 是基于事件驱动的,JVM 每执行到一定的逻辑就会调用一些事件的回调接口(如果有的话),这些接口可以供开发者扩展自己的逻辑。
比如最常见的,我们想在某个类的字节码文件读取之后、类定义之前修改相关的字节码,从而使创建的 class 对象是我们修改之后的字节码内容,那就可以实现一个回调函数赋给 jvmtiEnv(JVMTI 的运行时,通常一个 JVMTIAgent 对应一个 jvmtiEnv,但是也可以对应多个)的回调方法集合里的 ClassFileLoadHook,这样在接下来的类文件加载过程中都会调用到这个函数中
JVMTIAgent 其实就是一个动态库,利用 JVMTI 暴露出来的一些接口来干一些我们想做、但是正常情况下又做不到的事情,不过为了和普通的动态库进行区分