javaAgent Instrumentation与ClassFileTransformer学习总结

一个代理实现ClassFileTransformer接口用于改变运行时的字节码(class File),这个改变发生在jvm加载这个类之前。对所有的类加载器有效。

class File这个术语定义于虚拟机规范3.1,指的是字节码的byte数组,而不是文件系统中的class文件。

接口中只有一个方法:

byte[]
    transform(  ClassLoader         loader,
                String              className,
                Class<?>            classBeingRedefined,
                ProtectionDomain    protectionDomain,
                byte[]              classfileBuffer)
        throws IllegalClassFormatException;

ClassFileTransformer需要添加到Instrumentation实例中才能生效。

获取Instrumentation实例的方法有2种:

虚拟机启动时,通过agent class的premain方法获得
虚拟机启动后,通过agent class的agentmain方法获得
一旦agent参数获取到一个instrumentation,agent将会在任意时候调用实例中的方法。

agent应该以jar包的形式存在,也就是说agent所在的类需要单独打包一个jar包,jar包的manifest文件指定agent class。文件中包含Premain-Class属性,agent class类必须实现public static premain 方法,实际应用的main方法在这个方法之后执行。
premain 方法有2种签名,虚拟机优先调用

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

如果没有上一种,则调用下一种

public static void premain(String agentArgs); 

通过这个 -javaagent:jarpath[=options] 参数,启动实际应用,就会自带agent。如果agent启动失败,jvm会终止。
在虚拟机启动后,启动agent需要满足以下条件

agent所在 的jar包的manifest文件中必须包含Agent-Class属性,值为agent class。
agent类必须有public static agentmain方法。
系统类加载器必须支持添加一个agent的jar包到系统类路径system class path
这个方法也有2种签名,优先加载第一种,第一种没有,就加载第二种。

public static void agentmain(String agentArgs, Instrumentation inst); 

public static void agentmain(String agentArgs);

如果agent是在jvm启动后启动,那么premain就不会执行了。也就是说一个agent的2种方法只会启动一种。premain和agentmain是二选一的。
agentmain抛出异常,不会导致jvm终止。

第二种启动方式,先用jps获取进程id,然后启动agentjar包。
VirtualMachine 在jdk的lib下面的tools.jar中,如果不在classpath的话,要加进去。

VirtualMachine vm = VirtualMachine.attach("3134");
 try { 
 	vm.loadAgent("/../agent.jar"); 
 } finally 
 { 
 	vm.detach(); 
}

agent的jar包中manifest中可以有的属性:
属性 作用
Premain-Class 指定代理类
Agent-Class 指定代理类
Boot-Class-Path 指定bootstrap类加载器的搜索路径,在平台指定的查找路径失败的时候生效, 可选
Can-Redefine-Classes 是否需要重新定义所有类,默认为false,可选。
Can-Retransform-Classes 是否需要retransform,默认为false,可选
有两种ClassFileTransformer,根据canRetransform决定是哪一种。
在向Instrumentation#addTransformer添加转换器的时候,会指定canRetransform,默认为false。决定retransformation是否可用。

一旦一个transformer被注册到instrumentation中,每当一个类被定义(ClassLoader.defineClass)或被重新定义(Instrumentation.redefineClasses)时,它都会被调用。

如果retransformation可用,那么一个类被retransformation(Instrumentation.retransformClasses)时,transformer也会被调用。

存在多个transformers时,每个transformer会进行链式调用。

多个transformers调用顺序:

Retransformation不可用的
Retransformation不可用的native 的transformation
Retransformation可用的
Retransformation可用的native 的transformation
发生retransformations的时候,Retransformation不可用的transformers不会被调用。
同一种transformers按照注册顺序执行。
native的transformers通过ClassFileLoadHook提供。

如果一个transformer不想改变任何代码,那么返回null。否则,应该创建一个新的byte[],不能修改classfileBuffer。

一个transformer抛出异常,后续的transformer依然会执行,抛异常和返回Null效果相同。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Agent是Arthas使用的技术,是Skywalking使用的技术,是一份十分重要的技术。 课程的稀缺性在此之前,市面上并没有针对Java Agent进行系统介绍的课程。 通过搜索引擎查找,会发现与Java Agent相关的内容大多是个人知识总结分享的内容。这些内容有如下特点:内容质量不一详略程度不一学习难度千差万别总体上来说,学习者很难有一个整体认知、系统学习的过程。 课程的设计目标 在构思课程内容时,本课程带有以下目标:课程学习梯度:从简单到复杂,让学习者有一个循序渐进的理解过程。构造完整、统一的知识体系:不是零散的知识点堆砌,而是有一个统一的贯穿始终的知识框架。具有可操作性的代码示例,不只是讲概念,更注意于实践。课程内容安排 本课程通过四章内容对Java Agent相关知识进行讲解:第一章,介绍Agent Jar的三个组成部分:Manifest、Agent ClassClassFileTransformer。第二章,介绍Agent Jar的两种启动方式:从命令行启动和使用Attach机制启动。第三章,介绍如何利用Instrumentation API来实现Agent Jar的功能。第四章,Java Agent的应用与技巧。 通过本课程的学习,让同学们更好地建立起一个完整的知识体系:  讲师介绍我叫刘森,南京师范大学研究生毕业,2015年获得信息系统项目管理师(高级),2014年获得系统集成项目管理工程师(中级)。 目前,我的课程都是围绕着“Java字节码”技术展开: 《Java Agent基础篇》是在一个运行JVM当中提供修改字节码的机会《Java ASM系列》(免费课程)是一个操作字节码的类库《Java 8 ClassFile》专注于字节码的理论知识,入选为“51CTO数字化人才证书项目认证课程” 因此,我对字节码技术有较为深入的研究和理解,大家想学习字节码的技术可以找我:字节码技术找刘森,轻松学习又省心~~~ 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值