终于知道 Java agent 怎么重写字节码了

本文介绍了Java的Instrument机制,允许在JVM启动前或后修改字节码,实现运行时AOP。详细讲解了如何使用Java agent,包括启动前加载、启动后加载,以及manifest文件、Instrumentation接口和字节码修改技术如ASM、Javassist等。
摘要由CSDN通过智能技术生成

作者:丁仪 来源:https://chengxuzhixin.com/blog/post/Javaagent-zen-me-zhong-xie-zi-jie-ma.html

Java 自从 JDK 1.5 开始提供了 Instrument 机制,允许使用单独的 agent 获取 JVM 信息、动态修改 class 字节码,可以实现无侵入的运行时 AOP。使用 Java agent 可以在 JVM 启动前(JDK 1.5+)或启动后(JDK 1.6+)修改字节码,实现运行时数据的采集和回放(如 doom),也可以用于实时查看线上运行情况(如 arthas)。

 

启动前加载 agent

启动前加载 agent 可以在 Java 启动命令中,加入 javaagent 选项来启动代理。命令格式是:

-javaagent:jarpath [=options]

其中,jarpath 是代理 jar 文件的路径,options是传给代理的入参数据。javaagent 命令可以使用多次从而创建多个代理,且多个代理可以使用相同的 jarpath。

用于代理的 jar 文件需要满足如下要求:

  • manifest 文件中必须指定 Premain-Class 属性,属性的值是代理类的全路径名称;
  • 代理类必须实现一个 premain 方法。

premain 方法有两个可用的定义, JVM 首先尝试调用:

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

如果该方法未实现,JVM 再次尝试调用:

public static void premain(String agentArgs);

 

在 options 配置的入参,会通过 agentArgs 参数传入,由开发者自行解析字符串的内容。如果使用 javaagent 命令创建了多个代理,JVM 会依次调用每个代理的 premain 方法,然后才会调用 main 方法。所以 premain 方法必须返回,否则将无法启动。

代理类会使用系统类加载器( ClassLoader.getSystemClassLoader)来加载,因此 premain 会和 main 方法拥有相同的安全和加载器规则。JVM 不限制 premain 的实现,main 方法能做的事情,premain 都可以做。

 

启动后加载 agent

除了 premain 方法,JVM(1.6 及以后)还支持在启动之后启动代理。用于代理的 jar 文件需要满足如下要求:

  • manifest 文件中必须指定 Agent-Class 属性,属性的值是代理类的全路径名称;
  • 代理类必须实现一个 public static 类型的 agentmain 方法;
  • 系统类加载器( ClassLoader.getSystemClassLoader)必须支持将代理 jar 文件添加到系统类路径的机制。

agentmain 方法有两个可用的定义, JVM 首先尝试调用:

public static void agentmain(String agentA

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值