Java agent又叫作Java 探针,本文将从如下四个问题出发来深刻浅出了解下Java agentjava
Java agent是在JDK1.5引入的,是一种能够动态修改Java字节码的技术。java类编译以后造成字节码被JVM执行,JVM在执行这些字节码以前获取这些字节码信息,而且对这些字节码进行修改,来完成一些额外的功能,这种就是java agent技术。框架
1.java agent可以在加载java字节码以前进行拦截并对字节码进行修改eclipse
2.在jvm运行期间修改已经加载的字节码jvm
经过以上两种就能够实如今一些框架或是技术的采集点进行字节码修改,能够对应用进行监控,或是对执行指定方法或是接口时额外添加操做(打印日志、打印方法执行时间、采集方法的入参和结果等)ide
了解java agent的实现原理就必须先了解java的类加载机制(还不了解的自行了解),这个是了解java agent的前提。函数
其次须要了解的是JVMTI以及JVMTIAgent,下面分别介绍下工具
JVMTI是JVM Tool Interface的缩写,是JVM暴露出来给用户扩展使用的接口集合,JVMTI是基于事件驱动的,JVM每执行必定的逻辑就会调用一些事件的回调接口,这些接口能够给用户自行扩展来实现本身的逻辑idea
JVMTIAgent是一个动态库,利用JVMTI暴露出来的接口实现用户自行的逻辑(eclipse、idea等工具等代码调试就是经过这个实现的)spa
JVMTIAgent主要有三个方法,线程
Agent_OnLoad方法,若是agent在启动时加载,就执行这个方法
Agent_OnAttach方法,若是agent不是在启动的时候加载的,是咱们先attach到目标线程上,而后对对应的目标进程发送load命令来加载agent,在加载过程当中调用Agent_OnAttach函数
Agent_OnUnload方法,在agent作卸载掉时候调用
instrument agent实现了Agent_OnLoad方法和Agent_OnAttach方法,也就是即能在启动的时候加载agent,也能够在运行期来加动态加载agent,运行期动态加载agent依赖JVM的attach机制实现,经过发送load命令来加载agent
jvm attach机制上JVM提供的一种JVM进程间通讯的功能,能让一个进程传命令给另外一个进程,并进行一些内部的操做,好比进行线程dump,那么就须要执行jstack进行,而后把pid等参数传递给须要dump的线程来执行,这就是一种java attach。
第一次类加载的时候要求被transform的场景,在加载类文件的时候发出ClassFileLoad事件,交给instrument agent来调用java agent里注册的ClassFileTransformer实现字节码的修改
类从新定义,主要用在已经被加载的类上
原理了解清楚了就须要实现,java agent实现字节码加强到过程大概是:
1.修改字节码、2.加载新到字节码、3.替换旧的字节码
第二步能够经过自定义ClassLoader来加载修改的字节码,第三步能够经过JVM加载或运行字节码时进行替换,那么第一步修改字节码该如何进行呢,至少大部分人时不会修改的,那么就须要使用工具来修改,
目前实现修改字节码的工具主要有ASM、Javassist和byte buddy,下一篇将着重介绍这三种字节码生成框架及用法