当前位置: 首页 > 科技观察

一篇文章解密Arthas实现原理

时间:2023-03-17 18:24:23 科技观察

前言上一篇介绍了Arthas应用诊断工具——入门及常用操作。想必大家和我一样对Arthas的强大功能印象深刻(如何在不重启的情况下attach到JVM,以及如何实现各种监控统计功能),今天我们就来解密Arthash的实现。提前爆料今日重要角色:Instrument、ASM。Instrument有一个问题是Arthas如何在不重启的情况下连接到JVM并开始进入正题。首先介绍一下Instrument。Instrumentation类提供用于控制Java语言程序代码的服务。Instrumentation可以达到在方法中插入额外字节码的目的,将正在使用的数据收集到指定的工具中。由于插入的字节码是附加的,因此这些更改不会修改原始程序的状态或行为。以这种方式实现的良性工具包括监控代理、分析器、覆盖分析器和事件记录器等。简单来说,Instrument就是“修改一个已有类的字节码,增强其逻辑,从开发者的角度可以理解为JVM层面的AOP编程”。SkyWalking和PinPoint等许多开源APM(ApplicationPerformanceMonitor)框架都是通过java.lang.instrument包提供的字节码增强实现的。在大多数情况下,我们使用Instrument字节码检测功能。Jdk5开始引入java.lang.instrument包。一开始只有premain方法(通过命令行使用外部代理jar包)创建/在现有工程中,写premain函数publicstaticvoidpremain(StringagentArgs,Instrumentationinst)。将项目打包成jar包,引入Maven插件maven-jar-plugin指定Premain-Class。通过指定Agent运行java-javaagent:代理Jar包的路径【=premain传入的参数】yourTarget.jarJdk6然后优化这个点。不再需要通过命令-javaagent指定引入代理Jar,而是使用agentmain在运行时通过attach工具激活指定的代理。可以通过addTransformer、retransformClasses、redefineClasses等对字节码进行增强和热替换。要创建/在现有项目中,编写agentmain函数publicstaticvoidagentmain(StringagentArgs,Instrumentationinst)。将项目打包成jar包,引入Maven插件maven-jar-plugin指定Premain-Class。直接通过attach工具加载Agent。》简单提一下Instrument的原理:Instrument的底层实现依赖于JVMTI(JVMToolInterface),它是JVM暴露给用户扩展的接口集合。JVMTI是事件驱动的。JVM每次执行某个逻辑时都会调用一些事件的回调接口(如果有的话),开发者可以利用这些接口来扩展自己的逻辑。JVMTIAgent是一个动态库,它使用JVMTI暴露的接口提供agentonload、agentonattach和agentonunload的功能。仪器代理可以理解为一类JVMTIAgent动态库,它的别名是JPLISAgent(JavaProgrammingLanguageInstrumentationServicesAgent),是用java语言编写的提供仪器服务支持的代理。现在ASM有了重写类的入口(Instrument),只需要结合第三方字节码编译工具就可以完成想要的功能。Arthas用于通过ASM动态生成类或者增强类,比如常用的Gradle在运行时生成一些基于ASM的类,CGLib也是基于ASM实现的(插一句题外话:JdkProxy是基于“反射机制”实现的)")"ASM"是一个通用的Java字节码运行和分析框架。它可用于以二进制形式直接修改现有类或动态生成类。ASM提供了一些通用的字节码转换和分析算法,可以从中构建自定义的复杂转换和代码分析工具。ASM可以直接生成二进制类文件,也可以在类加载到Java虚拟机之前动态改变类的行为。Java类存储在以严格格式定义的.class文件中。这些类文件有足够的元数据来解析类中的所有元素:类名、方法、属性和Java字节码(指令)。ASM从类文件中读取信息后,可以改变类行为,分析类信息,甚至可以根据用户要求生成新的类。ASM提供与其他Java字节码框架类似的功能,但更注重性能。因为它“被设计和实现为尽可能小和尽可能快”,所以它“非常适合在动态系统中使用”(但当然也可以以静态方式使用,例如在编译器中)。ASM字节码增强技术主要用于提高反射时的性能。如果单纯使用jdk反射调用,性能很低。但是在使用了字节码增强技术之后,反射调用的时间与直接调用的时间基本相当。.ASM:https://asm.ow2.io/index.html。《ASM字节码处理流程:》目标类类字节->ClassReader分析->ClassVisitor增强修改字节码->ClassWriter生成增强类字节。《Arthas如何在不重启的情况下附加到JVM(ASM+Instrument处理流程)》:目标类类字节->ClassReader分析->ClassVisitor增强修改字节码->ClassWriter生成增强类字节->通过Instrument分析加载新的类班级。