java instrument学习总结

Instrumentation介绍:

Java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。JavaSE5中使用JVM TI替代了JVM PI和JVM DI。提供一套代理机制,支持独立于JVM应用程序之外的程序以代理的方式连接和访问JVM。Instrumentation 的最大作用就是类定义的动态改变和操作。在Java SE5 及其后续版本当中,开发者可以在一个普通Java程序(带有 main 函数的 Java 类)运行时,通过 – javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序。

premain方式

在Java SE5时代,Instrument只提供了premain一种方式,即在真正的应用程序(包含main方法的程序)main方法启动前启动一个代理程序。例如使用如下命令:

[java]view plaincopy

java -javaagent:agent_jar_path[=options] java_app_name

[java]view plaincopy

java -javaagent:agent_jar_path[=options] java_app_name

可以在启动名为java_app_name的应用之前启动一个agent_jar_path指定位置的agent jar。 实现这样一个agent jar包,必须满足两个条件:

在这个jar包的manifest文件中包含Premain-Class属性,并且改属性的值为代理类全路径名。

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

当在命令行启动该代理jar时,VM会根据manifest中指定的代理类,使用于main类相同的系统类加载器(即ClassLoader.getSystemClassLoader()获得的加载器)加载代理类。在执行main方法前执行premain()方法。如果premain(String args, Instrumentation inst)和premain(String args)同时存在时,优先使用前者。其中方法参数args即命令中的options,类型为String(注意不是String[]),因此如果需要多个参数,需要在方法中自己处理(比如用";"分割多个参数之类);inst是运行时由VM自动传入的Instrumentation实例,可以用于获取VM信息。


premain简单实例

1、先定义一个简单的Hello实例

public classTestMain {

public static void main(String[]args){

People people=newPeople();

people.sayHello();

}

}

其中 People类定义如下:

public classPeople {

public voidsayHello(){

System.out.println("hello !!!!");

}

}

2、编写一个MyAgent实例:

public classMyAgent {

/**

* 该方法是一个类作为agent类必备的

* @paramagentArgs

* @paraminst

*/

public static void premain(String agentArgs,Instrumentation inst){

//加入ClassFileTransfomer

inst.addTransformer(new PeopleClassFileTransformer());

}

}

PeopleClassFileTransformer类定义如下,主要通过javassist修改sayHello方法字节码:

public classPeopleClassFileTransformerimplementsClassFileTransformer {

/**

* 通过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----\");");

returnctClass.toBytecode();

}catch(NotFoundException e) {

e.printStackTrace();

}catch(CannotCompileException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}

}

returnclassfileBuffer;

}

}

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

Manifest-Version: 1.0

Premain-Class:: com.yao.intrumentation.MyAgent

Created-By: 1.8.0_121

打包MyAgent文件成MyAgent.jar

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


4、运行结果如下:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,374评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,929评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 11,937评论 0 62
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,444评论 11 349
  • 岛边漫步融融,意匆匆。 怎敌风高夜黑,海浪汹。 往头路,屡回顾,了无踪。 待到风清云淡,再来重。
    悠然芬芳阅读 1,196评论 4 9