Java Instrument

作用

Java Instrument指的是可以用独立于应用程序之外的代理程序来监测和协助运行在JVM上的应用程序,包括但不限于获取JVM运行时状态,替换和修改类定义。

使用方法

Java SE5及以后的版本,可以在一个普通Java程序运行时,通过-javaagent参数制定一个特定的jar文件(包含Instrumentation代理)来启动Instrumentation的代理程序。

代理类必须提供一个public static void premain(String args, Instrumentation inst)或public static void premain(String args)方法。

在命令行启动该代理jar时,VM会根据manifest中指定的代理类,使用与main类相同的系统类加载器加载代理类,在执行main方法前执行premain()方法。

简单示例

一个简单的main类

main:

public class TestMain {
    public static void main(String[]args){
        People people = new People();
        people.sayHello();
    }
}

people类:

public classPeople {
    public voidsayHello(){
        System.out.println("hello !!!!");
    }
}

agent实例

public classMyAgent {
/**
* 该方法是一个类作为agent类必备的
* @paramagentArgs
* @paraminst
*/
public static void premain(String agentArgs,Instrumentation inst){
    //加入ClassFileTransfomer
    inst.addTransformer(new PeopleClassFileTransformer());
    }
}

PeopleClassFileTransformer类,主要通过javassist修改sayHello方法字节码

public class PeopleClassFileTransformerimplementsClassFileTransformer {

	/**
	* 通过javassist修改字节码
	* @paramloader
	* @paramclassName
	* @paramclassBeingRedefined
	* @paramprotectionDomain
	* @paramclassfileBuffer
	* @return
	* @throws IllegalClassFormatException
	*/
	
	@Override
	public byte[]transform(ClassLoader loader,String className,Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throwsIllegalClassFormatException {
		System.out.println("load class:" + className);
		if("com/yao/intrumentation/People".equals(className)) {
			try{
				//通过javassist修改sayHello方法字节码
				CtClass ctClass= ClassPool.getDefault().get(className.replace('/','.'));
				CtMethod sayHelloMethod=ctClass.getDeclaredMethod("sayHello");
				sayHelloMethod.insertBefore("System.out.println(\"before sayHello----\");");
				sayHelloMethod.insertAfter("System.out.println(\"after sayHello----\");");
				return ctClass.toBytecode();
			} catch (NotFoundException e) {
				e.printStackTrace();
			} catch (CannotCompileException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return classfileBuffer;
	}
}

然后编写MAINIFEST.MF文件如下:

Manifest-Version: 1.0
Premain-Class:: com.yao.intrumentation.MyAgent
Created-By: 1.8.0_121

打包MyAgent文件成MyAgent.jar

输出

在ideal运行配置界面中VM options输入-javaagent:E:/Java_Web/JavaSPI-master/target/classes/myagent.jar,即MyAgent.jar路径;

运行结果:
1931244-700827fd23807dd8

comments powered by Disqus