构建本身的监测器【2】-javaagent参数使用

 javaAgent

 javaAgent是从JDK1.5及之后引入的,在1.5以前没法使用,也能够叫作java代理。

1. 代理 (agent) 是在你的main方法前的一个拦截器 (interceptor),也就是在main方法执行以前,执行agent的代码。java

agent的代码与你的main方法在同一个JVM中运行,并被同一个system classloader装载,被同一的安全策略 (security policy) 和上下文 (context) 所管理。安全

那么怎样写一个java agent? 在java5和java6中只须要实现premain这个方法:
public static void premain(String agentArgs, Instrumentation inst) 

例如:

package seeeyou.monitor;

import java.lang.instrument.Instrumentation;

public class MyAgent {
	public static void premain(String agentOps, Instrumentation inst){
		System.out.println(agentOps);
	}
}

若是找不到上面的这种premain的定义,还会尝试调用下面的这种premain定义:
public static void premain(String agentArgs)

2.写完这个代理类后,须要打成jar包,在jar包里面的 META-INF/MAINIFEST.MF 必须包含 Premain-Class这个属性。
以下:
Manifest-Version: 1.0
Premain-Class: seeeyou.monitor.MyAgent
Can-Redefine-Classes: true
须要注意的是,第四行是空行的,这一行必须有,不然绝对会报错。
目录结构基本以下图:


3.在一个java应用中,-javaagent这个参数的个数是不限的,你能够指定多个javaagent,全部的javaagent会按顺序执行,执行完各个agent以后,再执行main方法。好比
set JAVA_OPTS=%JAVA_OPTS% -javaagent:D:/tools/myagent1.jar  -javaagent:D:/tools/myagent2.jar  -javaagent:D:/tools/myagent3.jar
那么执行顺序就是:myagent1.premain  -> myagent2.premain -> myagent.premain  ->myprogram.main

4.放在main方法以后的premain方法是不会被执行的。好比这个运行:
jar -javaagent:D:/tools/myagent1.jar -jar myprogram.jar  -javaagent:D:/tools/myagent2.jar  -javaagent:D:/tools/myagent3.jar 
这个执行顺序就是:myagent1.premain  -> myprogram.main -> myagent2.premain  ->myagent3.premain
5. 每个java agent 均可以接收一个字符串类型的参数,也就是premain中的 agentArgs ,这个agentArgs是经过java option中定义的。
如: java - javaagent :myagent.jar=thisIsAgentArgs -jar MyProgram.jar

myagent中premain接收到的agentArgs的值将是”thisIsAgentArgs” (不包括双引号)this

6. 参数中的Instrumentation:经过参数中的Instrumentation inst,添加本身定义的ClassFileTransformer,来改变class文件。关于instrument,后面再介绍
7.经过java agent就能够不用修改原有的java程序代码,经过agent的形式来修改或者加强程序了,或者作热启动等等。