字节码插桩之Java Agent

字节码插桩之Java Agent

本篇文章将详细讲解有关Java Agent的知识,揭开它神秘的面纱,帮助开发人员了解它的黑魔法,帮助我们完成更多业务需求

What is Java Agent

Java Agent又称为Java探针,它提供了向现有已编译的Java类添加字节码的功能,相当于字节码插桩的入口;通过使用Java Instrumentation API,它能够侵入运行在JVM上的应用程序,进而修改应用程序中各种类的字节码。

在Java程序运行环境中,instrumentation是一种用于更改现有应用程序并向其添加代码的技术,可以在编译期间或者运行时执行此操作。它的优点就是,我们无需编辑源代码文件就能修改代码、更改它的行为;这非常有效,但也非常危险。

我们可以用它来实现很多功能,例如AOP

Java Agent是Java Instrumentation API的一部分,Java Instrumentation API提供了一种可以动态或者静态地修改字节码的机制,这意味着我们可以在不修改源代码的情况下向Java类中添加代码,这对Java应用程序有着很重要的影响

简单来说,Java Agent是一种特殊的jar文件,但是它包含遵循特殊约定的Java类,并在jar文件中的MANIFEST.MF(该文件通常存放在src/main/resources/META-INF文件夹下)文件中指定遵循特殊约定的Java类;在该特殊的类中有如下两类方法:

  • premain:在JVM启动时加载的Java Agent,例如使用java -jar命令启动jar文件时,添加-javaagent命令添加Java Agent;通俗来说就是在JVM初始化之后&main方法之前运行该agent

    其方法签名如下:

    public static void premain(String agentArgs, Instrumentation inst) 
    

    如果不包含上述方法,可选方法如下:

    public static void premain(String agentArgs) 
    
  • agentmain:使用Java Attach API将Java Agent动态加载到JVM中,在JVM初始化之后运行,可以在我们的main方法中通过Attach API调用该agent

    其方法签名如下:

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

应用程序是如何识别Java Agent的呢,答案就是MANIFEST.MF文件,该文件作为JAR文件的一部分包含jar文件的元数据信息,其中关于Java Agent的属性如下:

  • Premain-Class:当JVM启动时,该属性指定代理类,该类为包含premain方法的类,其值为全限定类名;如果在JVM启动时指定Java Agent则必须定义该属性
  • Agent-Class:如果实现支持在JVM启动后某个时间启动agent的机制,则此属性指定代理类;该类为包含agentmain方法的类,其值为全限定类名
  • Can-Readefine-Classes:定义Java Agent是否能够重定义Java类,其值为true or false,默认false
  • Can-Retransform-Classes:定义Java Agent能否重转换Java类,其值为true or false,默认false
  • Can-Set-Native-Method-Prefix:定义Java Agent能否设置所需的本机方法前缀,默认false
  • Boot-Class-Path:设置启动类加载器搜索的路径列表;查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径;按列出的顺序搜索路径,列表中的路径由一个或多个空格分开;路径使用分层 URI 的路径组件语法;如果该路径以斜杠字符(“/”)开头,则为绝对路径,否则为相对路径;相对路径根据代理 JAR 文件的绝对路径解析,忽略格式不正确的路径和不存在的路径,如果代理是在 VM 启动之后某一时刻启动的,则忽略不表示 JAR 文件的路径

在使用maven构建项目的过程中,我们可以通过pom.xml中的build属性设置maven-jar-plugin插件来自动生成MANIFEST.MF文件,示例如下:

	<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <!--true代表自动添加MANIFEST.MF文件-->
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <!--设置MANIFEST.MF文件的相关属性,类文件使用全限定类名-->
                        <manifestEntries>
                            <Premain-Class>cn.wygandwdn.agent.TestAgent</Premain-Class>
                            <Agent-Class>cn.wygandwdn.agent.TestAgent</Agent-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

Java Instrumentation API解析

官方文档:

java.instrument (Java SE 9 & JDK 9 )

java.lang.instrument (Java Platform SE 8 )

Java Instrumentation API主要提供了两个接口:Instrumentation、ClassFileTransformer:

  • Instrumentation:该类提供了向Java中插入代码的服务
  • ClassFileTransformer:顾名思义,该类就是类文件转换器接口,Java Agent提供该接口的实现,用于转换类文件

Instrumentation提供了一些添加&移除类转换器(ClassFileTransformer)、获取被JVM加载的类、重定义类、判断类是否支持重转换&重定义的接口,详细介绍如下:

  • addTransformer(ClassFileTransformer transformer, boolean canRetransform):注册类转换器。除了注册类转换器依赖的类定义以外,所有的类定义都会经过类转换器;当类加载时、重定义时、重转换时(如果canRetransform为true),会调用类转换器;如果一个类转换器抛出异常,JVM会依次调用其他类转换器;同一个类转换器实例可以被添加多次,但是强烈建议不要这么做,可以通过创建新的实例来避免这种做法
  • addTransformer(ClassFileTransformer transformer):注册类转换器,与addTransformer(transformer, false)作用相同
  • removeTransformer(ClassFileTransformer transformer):移除已注册的transformer,类定义将不再经过已经移除的transformer;移除策略为移除最近添加的transformer实例;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值