Java-Instrument 与 ClassFileTransformer

Java Instrument 能做什么?最大的作用?

使开发者可以构建一个独立于应用程序的代理程序 Agent,用来监控和协助运行在 JVM 上的程序,更重要的是能够替换和修改某些类的定义;

最大的作用:可以实现一种虚拟机级别支持的 AOP 实现方式;

基于 JVMTI 代理程序。

JVMTI:一套代理程序机制,为 JVM 相关工具提供的本地编程接口集合。

JVMTI 可以支持第三方工具程序以代理的方式连接和访问 JVM,并利用 JVMTI 提供的丰富的编程接口,完成很多跟 JVM 相关的功能。

java.lang.instrument.ClassFileTransformer 是什么,有什么作用?

ClassFileTransformer 当中的 transform 方法可以对类定义进行操作修改;

在类字节码载入 JVM 前,JVM 会调用 ClassFileTransformer.transform 方法,从而实现对类定义进行操作修改,实现 AOP 功能;相对于 JDK  动态代理、CGLIB 等 AOP 实现技术,不会生成新类,也不需要原类有接口;

两个核心 API:ClassFileTransformer、Instrumention?

ClassFileTransformer:定义了类加载前的预处理类;

Instrumentation:增强器

(1)add/removeTransformer:添加/删除 ClasFileTransformer;

(2)retransformerClasses:指定哪些类,在已加载的情况下,重新进行转换处理,即触发重新加载类定义;对于重新加载的类不能修改旧有的类声明,比如:不能增加属性、不能修改方法声明等;

(3)redefineClasses:指定哪些类,触发重新加载类定义,与上面不同的是不会重新进行转换处理,而是把处理结果 bytecode 直接给 JVM;

(4)getAllLoadedClasses:获取当前已加载的 Class 集合;

(5)getInitiatedClasses:获取由某个特定 ClassLoader 加载的类定义;

(6)getObjectSize:获得一个对象占用的空间大小;

(7)appendToBootstrapClassLoaderSearch/appentToSystemClassLoaderSearch:增加 BootstrapClassLoader/SystemClassLoader 搜索路径;

(8)isNativeMethodPrefixSupported/SetNativeMethodPrefix:判断 JVM 是否支持拦截 Native Method;

Java Instrument 工作原理?

在 JVM 启动时,通过 JVM 参数 -javaagent,传入 agent jar,Instrument Agent 被加载;

在 Instrument Agent 初始化时,注册了 JVMTI 初始化函数 eventHandlerVMinit;

在 JVM 启动时,会调用初始化函数 eventHandlerVMinit,启动了 Instrument Agent,用 sun.instrument.instrumentationImpl 类里的方法 loadClassAndCallPremain 方法去初始化 Premain-Class 指定类的 premain 方法;

初始化函数 eventHandlerVMinit,注册了 class 解析的 ClassFileLoadHook 函数;

在解析 Class 之前,JVM 调用 JVMTI 的 ClassFileLoadHook 函数,钩子函数调用 sun.instrument.instrumentationImpl 类里的 transform 方法,通过 TransformerManager 的 transformer 方法最终调用我们自定义的 Transformer 类的 transform 方法;

因为字节码在解析 Class 之前改的,直接使用修改后的字节码的数据流替代,最后进入 Class 解析,对整个 Class 解析无影响;

重新加载 Class 依然重新走 5-6 步骤;


https://www.jianshu.com/p/9f4e8dcb3e2f

https://www.jianshu.com/p/9d1a37bb8183

原文地址:https://www.cnblogs.com/jhxxb/p/11570503.html