当前位置: 首页 > news >正文

SkyWalking-2--Java Agent是什么?

1、Java Agent是什么?

Java Agent是Java虚拟机(JVM)提供的一种动态修改字节码的技术,是一种特殊类型的工具。允许开发者在类加载时或运行时对Java程序的行为进行监控、增强或修改。它是通过java.lang.instrument包和JVMTI(JVM Tool Interface)接口实现的,是实现非侵入式监控、性能分析、热修复、AOP(面向切面编程)等功能的核心技术。

Java Agent技术是基于Java Instrumentation API实现的,该API从JDK 5开始引入,并在后续版本中得到了增强。

2、核心概念

1、Instrumentation接口

Instrumentation是Java Agent的核心接口,提供的一套API,允许在类加载到JVM时对其进行转换。

API示例:

  • addTransformer(ClassFileTransformer transformer):注册字节码转换器,拦截并修改类加载时的字节码。
  • retransformClasses(Class<?>…、classes):重新转换已加载的类(触发字节码修改)。
  • redefineClasses(ClassDefinition[] definitions):直接替换已加载类的字节码(不改变类结构)。
  • getAllLoadedClasses():获取当前JVM中所有已加载的类。

实现方式:

  • 通过premain或agentmain方法传入的参数获取。

2、入口方法

(1)premain(JVM启动时加载)

在JVM启动时加载Agent,在main方法执行前被调用。

Java示例:

public static void premain(String args, Instrumentation inst) {inst.addTransformer(new MyClassTransformer());
}

解释:
在premain方法中通过jdk自定的Instrumentation加载类转换器;类转换器会在JVM加载类的时起作用,如果匹配是目标类会进行字节码修改,加入额外逻辑代码。

启动命令:(bash)

java -javaagent:myagent.jar -jar app.jar
(2)agentmain(运行时附加)

在JVM运行时动态附加Agent,通过Attach API实现。

Java示例:

public static void agentmain(String args, Instrumentation inst) {inst.addTransformer(new MyClassTransformer());
}

解释:
功能通premain,premain方法在启动jvm时触发加载类转换器;agentmain方法针对已经运行的JVM程序添加类转换器触发。

动态附加命令:(bash)

jattach <pid> load /path/to/myagent.jar

3、ClassFileTransformer接口

  • 作用:字节码转换器。定义字节码转换规则,通过transform方法拦截类加载过程并修改字节码。

Java示例:

public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] classfileBuffer) {if (className.equals("com/example/MyClass")) {// 使用ASM或Byte Buddy修改字节码return modifiedBytecode;}return null; // 不修改
}

3、工作原理

1、静态加载(JVM启动时加载)

流程:
(1)、JVM启动时通过-javaagent参数指定Agent JAR包。
(2)、JVM读取JAR的META-INF/MANIFEST.MF文件,找到Premain-Class配置的类。
(3)、调用该类的premain方法,传入Instrumentation实例。
(4)、在premain中注册ClassFileTransformer,拦截后续加载的类并修改字节码。

特点:

  • 适用于需要在应用启动前进行全局增强的场景(如性能监控、日志埋点)。

2、动态加载(运行时附加)

流程:
(1)、使用jattach或com.sun.tools.attach API将Agent动态附加到运行中的JVM。
(2)、JVM调用Agent的agentmain方法,传入Instrumentation实例。
(3)、通过retransformClasses或redefineClasses修改已加载类的字节码。

特点:

  • 适用于运行时调试、热修复、动态分析等场景(如Arthas、JRebel)。

3、字节码增强的核心机制

  • 类加载拦截:JVM在加载类时触发ClassFileTransformer的transform方法,允许修改字节码。
  • 字节码修改工具:常用工具包括ASM、Javassist、Byte Buddy,用于生成或修改字节码。

例如:

  • 在方法入口和出口插入性能监控代码。
  • 修改类的字段或方法逻辑(如热修复)。

4、典型应用场景

1、性能监控(APM)

  • 通过字节码增强在方法调用前后插入耗时统计代码,采集方法执行时间、调用链等数据。
  • 示例工具:SkyWalking、Pinpoint、New Relic。

2、热修复(HotFix)

  • 在运行时动态替换有缺陷的类定义,无需重启服务即可修复线上问题。
  • 实现方式:使用 redefineClasses 替换已加载类的字节码。

3、AOP(面向切面编程)

  • 实现日志记录、权限校验、事务管理等通用逻辑的动态植入。
  • 示例框架:Spring AOP、AspectJ。

4、安全防护

  • 检测危险操作(如反射调用Runtime.exec()),或对敏感类进行加密和解密。

5、代码覆盖率分析

  • 通过插桩记录代码执行路径,生成覆盖率报告(如JaCoCo)。

6、调试与诊断工具

  • 动态附加到JVM,实时分析线程、内存、GC状态(如Arthas、VisualVM)。

5、开发步骤示例

1、编写Agent类

  • 实现premain或agentmain方法,并注册ClassFileTransformer。

代码示例:

public class MyAgent {
public static void premain(String args, Instrumentation inst) {// 注册一个Transformerinst.addTransformer((loader, className, classBeingRedefined,protectionDomain, classfileBuffer) -> {if (className.equals("com/example/MyClass")) {return modifyBytecode(classfileBuffer);}return null;});}private static byte[] modifyBytecode(byte[] originalBytes) {// 使用ASM或Byte Buddy修改字节码return modifiedBytes;}
}

2、配置MANIFEST.MF

  • 在META-INF/MANIFEST.MF中指定入口类和能力。

MANIFEST.MF示例:

Manifest-Version: 1.0
Premain-Class: MyAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

3、打包Agent JAR

  • 使用Maven或Gradle打包包含依赖的JAR文件。

Maven配置示例:

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile></archive></configuration></plugin></plugins>
</build>

4、运行测试

  • 静态加载:
    bash示例:
java -javaagent:myagent.jar -jar app.jar
  • 动态附加:
    bash示例:
jattach <pid> load /path/to/myagent.jar

6、优势与挑战

在这里插入图片描述

7、其他问题

1、类加载器隔离问题

  • 不同类加载器加载的类是相互隔离的,Agent需要确保能够访问目标类的类加载器。

2、安全机制

  • 通过JVM参数(如-XX:WhiteBoxAPI)限制Agent的权限。
  • 使用签名验证确保Agent包的可信性。

3、与AOP的区别

  • AOP(如Spring AOP)基于代理模式,只能拦截公共方法;Java Agent可以修改任意类的字节码,包括私有方法和字段。

8、总结

Java Agent是一种强大的字节码操作技术,通过动态修改字节码实现对Java程序的非侵入式增强。它广泛应用于性能监控、链路追踪、热修复、AOP、安全防护等领域,是构建高可观测性、高可用性系统的利器。尽管开发复杂度较高,但其灵活性和强大功能使其成为现代Java开发不可或缺的工具。

向阳前行,Dare To Be!!!

http://www.dtcms.com/a/323082.html

相关文章:

  • Qt与嵌入式设备中的字节序问题
  • 客服Agent革命:智能客服系统的技术实现与效果评估
  • 八、《DaaS(设备即服务):企业轻资产化新路径》--从97.4%首期投入削减到AI算力高效迭代的范式革命
  • ​​​​​​​【Datawhale AI夏令营】多模态RAG财报问答挑战赛:学习笔记与上分思考
  • “黑影御剑飞行”视频引发的思考
  • 差分放大电路的四种接法
  • react-window
  • 组合期权:垂直价差
  • Playwright C# 自动登录并上传 Excel 文件 的可运行示例
  • Java 数据类型与内存模型:从字节到引用的底层逻辑
  • 数字图像处理基础——opencv库(Python)
  • C语言库中的字符函数
  • 基于 RAUC 的 Jetson OTA 升级全攻略
  • Vue和Springboot初步前后端分离建立项目连接(解决前后端跨域问题)
  • linux安装php
  • 机器学习 K-Means聚类 无监督学习
  • AI 算法优化实战指南:从理论到部署的全流程优化策略
  • VSCode添加Python、Java注释技巧、模板
  • 企业级web应用服务器TOMCAT入门详解
  • 2G内存的服务器用宝塔安装php的fileinfo拓展时总是卡死无法安装成功的解决办法
  • Atto Round 1 (Codeforces Round 1041, Div. 1 + Div. 2) C、D、E
  • 数码管的使用(STC8)
  • 美股高频分时Tick数据分钟级解析
  • Leetcode-19. 删除链表的倒数第 N 个结点
  • 机器学习第七课之支持向量机SVM
  • 【线性代数】线性方程组与矩阵——(3)线性方程组解的结构
  • 如何在 Windows 下使用 WSL 安装 Ubuntu 并配置国内镜像
  • 力扣前200题字符串总结
  • 差分放大电路分析与仿真
  • 阿里Qwen-Image本地部署详细指南