`Java Agent`可以理解为一个`JVM`虚拟机的插件,`agent`插件`jar`包通过`JVMTI`
完成加载,JVMTI全称JVM Tool Interface
,是JVM
暴露出来的一些供用户扩展的接口集合。JVMTI
是基于事件驱动的,JVM
每执行到一定的逻辑就会调用一些事件的回调接口(如果有的话),这些接口可以供开发者扩展自己的逻辑。最终借助JPLISAgent(Java Programming Language Instrumentation Services Agent)
完成对目标代码的修改。
JVMTIAgent
动态库提供以下函数:
启动时加载
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
运行时加载
JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
卸载时调用
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm);
Agent
启动时加载流程:
1.创建并初始化 JPLISAgent
2.监听 VMInit
事件,在 vm
初始化完成之后做下面的事情:
<aside> ✅ 创建 InstrumentationImpl 对象
</aside>
<aside> ✅ 监听 ClassFileLoadHook 事件loadClassAndCallPremain方法,在这个方法里会调用 javaagent 里 MANIFEST.MF 里指定的Premain-Class类的 premain 方法
</aside>
3.解析 javaagent
里 MANIFEST.MF
里的参数,并根据这些参数来设置 JPLISAgent
里的一些内容
源码编译方式打包:
mvn -Dmaven.test.skip=true clean install -U
#目录下是agent的打包文件
cd femas-agent/femas-agent
文件目录
├── femas-agent
│ ├── config #agent配置文件
| | ├── femas.yaml #femas组件相关配置
| | ├── plugin.yaml #premain需要加载的plugin相关配置
│ ├── plugins #plugin jar包
| | ├── plugin.jar
│ └── femas-agent.jar #-javaagent指向的jar
将femas-agent
包放在服务器的任意位置,在服务启动参数加上:
-javaagent:"/绝对路径/femas-agent.jar" //指向femas-agent文件夹中的femas-agent.jar