java agent基础原理

本文介绍如何利用JavaAgent技术和ByteBuddy库实现代码增强,包括JavaAgent的基本原理及其实现方式,以及ByteBuddy作为强大的字节码操作库的优势和应用场景。

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

1),如何实现代码增强
java agent
Skywallking监控JVM主要使用java agent
(ps: java agent可以在不修改目标应用达到代码增强的目的,就好像spring的aop一样,但是java agent是直接修改字节码,而不是通过创建代理类。例如skywalking就是使用java agent技术,为目标应用代码植入监控代码,监控代码进行数据统计上报的。这种方式实现了解耦,通用的功能)

Java agent 实现非常简单我们只需要定义一个类,然后类中定义一个方法名为premain 的方法,然后在MANIFEST.MF 文件中添加以下内容:
Manifest-Version: 1.0
Agent-Class: org.agent.AgentTest
Premain-Class: org.agent.AgentTest
Can-Redefine-Classes: true
Can-Retransform-Classes: true

Premain 有两种实现方式,区别在于选择带有Instrumentation参数,可以使用该变量完成代码的热替换

public class DemoAgent {
    /**
     * 该方法在main方法之前运行,与main方法运行在同一个JVM中
     */
    public static void premain(String arg, Instrumentation instrumentation) {
        System.out.println("agent的premain(String arg, Instrumentation instrumentation)方法");
//        instrumentation.addTransformer();
    }
 
    /**
     * 若不存在 premain(String agentArgs, Instrumentation inst),
     * 则会执行 premain(String agentArgs)
     */
    public static void premain(String arg) {
        System.out.println("agent的premain(String arg)方法");
    }

Bytebuddy
Byte Buddy是一个字节码生成和操作库,用于在Java应用程序运行时创建和修改Java类,而无需编译器的帮助。除了Java类库附带的代码生成实用程序外,Byte Buddy还允许创建任意类,并且不限于实现用于创建运行时代理的接口。此外,Byte Buddy提供了一种方便的API,可以使用Java代理或在构建过程中手动更改类。

• 无需理解字节码指令,即可使用简单的 API 就能很容易操作字节码,控制类和方法。
• 已支持Java 11,库轻量,仅取决于Java字节代码解析器库ASM的访问者API,它本身不需要任何其他依赖项。
• 比起JDK动态代理、cglib、Javassist,Byte Buddy在性能上具有一定的优势。

附maven依赖

    <dependencies>
        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy</artifactId>
            <version>LATEST</version>
        </dependency>
    </dependencies>

    <build>
<!--        <resources>
            <resource>
            &lt;!&ndash; 设定主资源目录  &ndash;&gt;
                <directory>src</directory>
            </resource>
        </resources>-->
        <plugins>
            <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <shadedArtifactAttached>false</shadedArtifactAttached>
                            <createDependencyReducedPom>true</createDependencyReducedPom>
                            <createSourcesJar>true</createSourcesJar>
                            <shadeSourcesContent>true</shadeSourcesContent>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <!-- 包含premain方法的类 -->
                                        <Premain-Class>com.dyb.agent.DemoAgent</Premain-Class>
                                        <!-- 对目标类字节码操作权限 -->
                                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                                        <!-- 对目标类字节码操作权限 -->
                                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>

    </build>
### OpenTelemetry Java Agent 的工作机制与原理 #### 1. 背景介绍 OpenTelemetry 是一种用于收集和导出遥测数据的标准框架,支持分布式追踪、指标以及日志等功能[^4]。其中,OpenTelemetry Java Agent 是一个轻量级的 JVM 插件,能够在不修改应用代码的情况下自动捕获性能指标和分布式追踪数据。 #### 2. Java Agent 基础概念 Java Agent 是一种特殊的类库,在 JVM 启动时加载并允许开发者对字节码进行操作的技术。对于 VM 启动后加载的 Java Agent,`Instrumentation` 接口会通过 `agentmain` 方法传入程序。该方法在主函数 (`main`) 开始运行后才会被调用,因此适合在程序运行期间动态地替换字节码逻辑[^2]。 #### 3. 动态注入机制 为了实现动态注入功能,Java 提供了 Attach API 技术。具体来说,应用程序可以通过虚拟机提供的 `attach(pid)` 方法将代理程序连接到目标进程中,并利用 `loadAgent(AgentJarPath)` 将 Agent Jar 文件注入至对应进程。随后,目标进程会触发 `agentmain` 方法完成初始化工作。这种技术广泛应用于多种开源诊断工具中,例如 BTrace 和 Alibaba Arthas。 #### 4. OpenTelemetry Java Agent 实现细节 OpenTelemetry Java Agent 利用了上述基础能力实现了自动化监控的功能。以下是其实现的关键部分: - **字节码增强** 使用 ASM 或 Byte Buddy 等库拦截特定的方法调用并对它们附加额外的行为(如记录时间戳或上下文信息)。这种方式无需更改原始业务代码即可获取所需的数据。 - **自定义传播器接口** 针对不同协议需求,OpenTelemetry 定义了两个核心接口——`TextMapSetter` 和 `TextMapGetter` 来处理跨服务间通信中的元数据传递问题。用户可以根据实际场景自行扩展这两部分内容以适配更多平台特性[^3]。 - **集成第三方组件** 默认情况下已经内置了许多常见框架的支持模块(Spring Boot, Hibernate ORM 等),同时也鼓励社区贡献新的插件来覆盖更广泛的生态系统范围。 #### 5. 数据传输与存储 采集完毕后的跟踪事件会被序列化并通过 gRPC 协议推送到远端接收方(Collector Service)。最终由后者负责持久化保存或者进一步分析展示给运维人员查看。 ```java // 示例:如何配置 OpenTelemetry Exporter 发送数据到 Prometheus SdkTracerProvider tracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(new OtlpGrpcSpanExporter())) .build(); OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(tracerProvider) .buildAndRegisterGlobal(); ``` --- ####
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值