Java agent从0到1的踩坑过程

本文深入探讨Java Agent技术,从概念到实践,包括如何构建代理程序,实现虚拟机级别的AOP功能,以及复杂案例如装饰线程池的Runnable、Callable类。详细介绍了不同打包方式、配置启动项,并解决常见错误。

1. java agent技术简介

在JDK1.5之后,可以使用agent技术构建一个独立于应用程序的代理程序(即Agent)。可以用来协助监测、运行甚至替换其他JVM上的程序。使用它可以实现虚拟机级别的AOP功能。

2. Agent案例

2.1 最简单的Agent案例

2.1.1 代码

基础的demo可以参考:
一个最简单的javaagent demo实例

2.1.2 打包方式

注意:这种打包方式和maven的打包方式是不同的,maven的打包方式可见下文。

在此处进入
生成Build Artifact是在Build->Build Artifact下生成的。
在这里插入图片描述

2.1.3 生成jar包时,需要注意编译的JDK版本。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 复杂的Agent案例

目的:AOP装饰线程池的Runnable、Callable类。
项目对应的GitHub地址

2.2.1 配置启动项

启动项的地址为生成jar的绝对地址:

-javaagent:/Users/yexuerui/Documents/veradm/agenttest/out/artifacts/agenttest_jar/agenttest.jar

配置启动项

2.2.2 生成jar包

使用idea去打包

因为修改的是JDK的标准库的类,而标准库的类是由bootstrap class loader类加载器加载的,而上面修改的ThreadPoolExecutor类引用了agent类的代码,所以agent的jar包需要加到boot class path上。即需要去配置MF文件中的Boot-Class-Path

如果不修改,会出现:
在这里插入图片描述
但是仅仅配置Boot-Class-Path: agenttest.jar依旧javassist的类出现NoClassDefFoundError异常。

所以当使用idea进行打包时,需要如下配置MF文件:

Manifest-Version: 1.0
Class-Path: spotbugs-annotations-4.1.1.jar jsr305-3.0.2.jar javassist-
 3.23.2-GA.jar
Premain-Class: com.yyy.agent.demo.agent.TtlAgent
Can-Redefine-Classes: true
Can-Set-Native-Method-Prefix: true
Boot-Class-Path: agenttest.jar javassist-3.23.2-GA.jar
Can-Retransform-Classes: true

最优的配置是将javassist-3.23.2-GA.jar打入到agenttest.jar中,可以使用下面的maven打包的方式。

使用maven去打包

  1. 配置MF文件,打包的时候,自动生成MF文件配置:
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Premain-Class>com.yyy.agent.demo.agent.TtlAgent</Premain-Class>
                            <Boot-Class-Path>${project.artifactId}-${project.version}.jar</Boot-Class-Path>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                            <Can-Set-Native-Method-Prefix>false</Can-Set-Native-Method-Prefix>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
  1. 将javassist的jar包内容打入到生成的jar包中

maven-shade-plugin介绍及使用

  1. 将依赖的jar包打包到当前jar包(常规打包是不会将所依赖jar包打进来的);
  2. 对依赖的jar包进行重命名(用于类的隔离);
            <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <id>shade-when-package</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <relocations>
                                <relocation>
                                    <pattern>javassist</pattern>
                                    <shadedPattern>com.yyy.agent.demo.agent.internal.javassist</shadedPattern>
                                </relocation>
                            </relocations>
                            <artifactSet>
                                <includes>
                                    <include>org.javassist:javassist</include>
                                </includes>
                            </artifactSet>
                            <shadeSourcesContent>true</shadeSourcesContent>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
  1. 生成jar包的命令
 mvn clean install

遇到的问题:
在这里插入图片描述

生成jar包的时候,可能会出现这个问题,看上去是网络超时。原因是:连接的公司内网,所以不能进行下载。解决方案就是使用手机热点进行下载。

  1. 最终生成的jar包
    在这里插入图片描述

项目对应的GitHub地址

3. 推荐阅读

调用链上下文跨线程传递

☆基于Java Instrument的Agent实现

注:下文中的 *** 代表文件名中的组件名称。 # 包含: 中文-英文对照文档:【***-javadoc-API文档-中文(简体)-英语-对照版.zip】 jar包下载地址:【***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: 中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值