写在前面
本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和文献引用请见100个问题搞定Java虚拟机
解答
Java Agent 概述
Java Agent 本质上是 JDK 提供的一个工具。
在 JDK1.5 之后,可以使用 Java Agent 技术构建一个独立于应用程序的代理程序(即Agent)。
可以用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的 AOP 功能,比如字节码注入。
Java Agent 的作用
我们可以通过 Java Agent 的类加载拦截功能,修改某个类所对应的字节码二进制数组,并利用这个修改过后的二进制数组完成接下来的类加载。
JavaAgent 是运行在 main 方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法。
我们之前专栏中提到的 Arthas 本质上就是通过 Java Agent 实现的。
关于 Arthas 请参考我的另一篇博客——震惊!原来 Arthas 入门这么简单!5 分钟就搞定了!
Java Agent 的问题
基于字节码注入的 profiler,可以统计程序运行过程中某些行为的出现次数。
如果需要收集 Java 核心类库的数据,那么我们需要小心避免无限递归调用。另外,我们还需通过自定义类加载器来解决命名空间的问题。
由于字节码注入会产生观察者效应,因此基于该技术的 profiler 所收集到的数据并不能反映程序的真实运行状态。它所反映的是程序在被注入的情况下的执行状态。
Java Agent 的底层实现原理
Java Agent 本质上是通过 c agent 来实现的。
C Agent 是一个事件驱动的工具实现接口,通常我们会在 C Agent 加载后的入口方案 Agent_OnLoad 处注册各个事件的钩子方法。
当Java虚拟机触发了这些事件时,便会调用对应的钩子方法。