何为java agent
java agent也可以称之为java代理,相当于在JVM级别做了AOP支持,我们可以在运行main方法之前对程序进行修改或新增逻辑。
怎么实现
java agent可以通过两种方式实现
- 静态挂载
首先需要实现premain方法,在这里会通过Instrumentation进行类修改,所以还需要实现Transformer,(本篇不对Instrumentation做详细阐述,可以自行百度学习。)
1 | typescript复制代码public class PreMainDemoAgent { |
1 | csharp复制代码public class PreMainTransformer implements ClassFileTransformer { |
- 动态挂载
动态挂载则需要定义agentmain方法,同样也需要定义对应的Transformer
1 | csharp复制代码public class AgentMainDemo { |
1 | java复制代码public class AgentMainTransformer implements ClassFileTransformer { |
代码编写完就可以进行配置了,这边直接应用maven进行配置,也可以定义在META-INF文件上。
1 | xml复制代码<plugin> |
原本以为到这里这个插件就可以使用了,直接mvn clean install打包成jar,在目标项目直接挂载跑起来测试,就遇到坑了。
这里我直接在项目里面跑,jvm配置如下:
遇到的问题&解决方案
- NoClassDefFoundError:javassist/ClassPool
这个现象是这样:执行后,我的agent代码跑到
CtClass demoClass = ClassPool.getDefault().get(“com.vernunft.agent.demo.controller.TestController”);
就没有继续往下执行,而且刚开始我用Exception捕获,日志竟然也打不出来,最后我用Throwable才打印出错误。
可以发现这打包时就没把依赖jar打入,得在maven上加入配置,把引的jar一起打入。
1 | xml复制代码<!-- 将依赖jar打入项目的插件--> |
标签的值为这里标记的
重新打包执行测试成功,按照预期返回结果。
- 动态挂载时报com.sun.tools.attach.AttachNotSupportedException: no providers installed
解决方案:在目标项目的pom文件增加tools.jar依赖
1 | xml复制代码<dependency> |
重新构建目标项目执行,发现问题解决~
最后附上目标项目的测试文件,动态挂载就是通过指定进程id,挂载对应的插件。
1 | less复制代码@RestController |
Over,因为踩坑才能学习更多的东西,fighting。
本文转载自: 掘金