Java探针之JavaAgent揭秘

JavaAgent是JDK1.5后引入的技术,允许在执行main()前修改字节码。它作为应用程序启动时的拦截器,通过-ClassFileTransformer对字节码进行修改,实现监控、日志记录等功能。使用JavaAgent需添加-premain方法和Instrumentation参数,配合ASM等工具,可实现强大的字节码操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java探针利用了javaAgent + ASM字节码注入工具实现了动态修改类文件的功能。这是很多arthas和APM应用监控系统如Skywalking的基础。

首先什么是JavaAgent呢?

什么是javaAgent?

JavaAgent 是JDK 1.5 以后引入的,也可以叫做Java代理。是一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能。

从用户使用层面来看,Java Agent 一般通过在应用启动参数中添加 -javaagent 参数添加 ClassFileTransformer 字节码转换器。 在 Java 虚拟机启动时,执 行main() 函数之前,Java 虚拟机会先找到 -javaagent 命令指定 jar 包,然后执行 premain-class 中的 premain() 方法。用一句概括其功能的话就是:main() 函数之前的一个拦截器
agent的代码与你的main方法在同一个JVM中运行;被同一个system classloader装载;被同一的安全策略 (security policy) 和上下文 (context) 所管理。

javaAgent可以实现的功能

1.javaAgent能够在执行java字节码生成Class对象之前进行拦截并对字节码进行修改
2.在jvm运行期间修改已经加载的字节码

通过以上两种就可以实现在一些框架或是技术的采集点进行字节码修改,可以对应用进行监控,或是对执行指定方法或是接口时额外添加操作(打印日志、打印方法执行时间、采集方法的入参和结果等)

使用入门:

  1. 编写一个maven项目,创建一个带有下列方法的java类。注意方法签名保持一致,参数Instrumentation inst也可省略。
public class MyAgent {
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("Hello Main Method, I'm premain Method from agent, agentOps:" + agentOps);
    }
}
  1. pom文件里添加下面的插件
<build>
   <plugins>
       <plugin>
           <!--引入maven-jar-plugin-->
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
           <version>2.6</version>
           <configuration>
               <archive>
                   <manifestEntries>
                     <!--这里添加premain方法的类全路径,maven会你生成manifest文件-->
                       <premain-class>com.jun.sail.agent.MyAgent</premain-class>
                   </manifestEntries>
               </archive>
           </configuration>
       </plugin>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <configuration>
               <source>8</source>
               <target>8</target>
           </configuration>
       </plugin>
   </plugins>
</build>
  1. 然后mvn clean package打包即可。看下打好的jar包,可以看到META-INF文件夹有个MANIFEST.MF文件,就是刚才插件的功劳。

  2. 最后找个项目(jar包启动的项目,如springboot项目),启动时添加jvm参数-javaagent:E:\code\my-java-agent\target\my-java-agent-1.0-SNAPSHOT.jar指到刚才打好的代理jar包。可以跟参数,对应着premain方法里的agentOps参数
    在这里插入图片描述

    即可在控制台看到先打印了Hello Main Method, I'm premain Method from agent, agentOps:123,然后才执行了main方法。

另外,其实IDE的debug模式启动时也是添加了javaAgent代理

在这里插入图片描述
从这里也可以看出Javaagent可以指定多个

上面只是简单介绍了JavaAgent的使用,那怎么去修改加载的类文件呢,这就涉及到了Instrumentation接口,这个才是agent实现更强大功能的核心所在!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值