JavaAgent 是JDK 1.5 以后引入的,也可以叫做Java代理。
java.lang.instrument包是Java中来增强JVM上的应用的一种方式,机制是在JVM启动前或启动后attach上去进行修改方法字节码的方式。
instrument包的用途很多,主要体现在对代码侵入低的优点上,例如一些监控不方便修改业务代码,但是可以使用这种方式在方法中植入特定逻辑,这种方式能够直接修改JVM中加载的字节码的内容,而不需要在像Spring AOP实现中创建新的代理类,所以在底层侵入更高,但是对开发者更透明。用于自动添加getter/setter方法的工具lombok就使用了这一技术。另外btrace和housemd等动态诊断工具也是用了instrument技术。
Java探针工具功能点:
1、支持方法执行耗时范围抓取设置,根据耗时范围抓取系统运行时出现在设置耗时范围的代码运行轨迹。
2、支持抓取特定的代码配置,方便对配置的特定方法进行抓取,过滤出关系的代码执行耗时情况。
3、支持APP层入口方法过滤,配置入口运行前的方法进行监控,相当于监控特有的方法耗时,进行方法专题分析。
4、支持入口方法参数输出功能,方便跟踪耗时高的时候对应的入参数。
5、提供WEB页面展示接口耗时展示、代码调用关系图展示、方法耗时百分比展示、可疑方法凸显功能。
JavaAgent 是运行在 main方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法。
那么如何实现一个 JavaAgent 呢?很简单,只需要增加 premain 方法即可。
eg:
package agent;
import java.lang.instrument.Instrumentation;
public class pre_MyProgram {
/**
* 该方法在main方法之前运行,与main方法运行在同一个JVM中
* 并被同一个System ClassLoader装载
* 被统一的安全策略(security policy)和上下文(context)管理
*
* @param agentOps
* @param inst
* @author SHANHY
* @create 2016年3月30日
*/
public static void premain(String agentOps,Instrumentation inst){
System.out.println("====premain 方法执行");
System.out.println(agentOps);
}
/**
* 如果不存在 premain(String agentOps, Instrumentation inst)
* 则会执行 premain(String agentOps)
*
* @param agentOps
* @author SHANHY
* @create 2016年3月30日
*/
public static void premain(String agentOps){
System.out.println("====premain方法执行2====");
System.out.println(agentOps);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Premain-Class: agent.pre_MyProgram
Can-Redefine-Classes: true
特别提醒:
(1)如果你把 -javaagent 放在 -jar 后面,则不会生效。也就是说,放在主程序后面的 agent 是无效的。
比如执行:
java -javaagent:G:\myagent.jar=Hello1 -javaagent:G:\myagent.jar=Hello2 -jar myapp.jar -javaagent:G:\myagent.jar=Hello3
(2)如果main函数忘了选择MF文件或是MF文件选择的不对,就会报错:
关于java的agent,可以参考java-agent-demo了解其具体实现和相应的原理~!