前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >javaAgent入门

javaAgent入门

原创
作者头像
杨不易呀
修改2023-11-20 16:32:07
3360
修改2023-11-20 16:32:07
举报
文章被收录于专栏:杨不易呀杨不易呀

前言

在Java编程语言中,Java Agent是一种特殊的Java程序,它可以在Java应用程序运行时修改或监视字节码。Java Agent通常通过Java虚拟机 (JVM) 的Instrumentation API来实现这一点。

Jdk1.5 以后引入了 javaAgent 技术,javaAgent 是运行在方法之前的拦截器,相当于是对字节码进行的一个 AOP 操作,利用 javaAgent 和 ASM 字节码技术,在 JVM 加载 class 二进制文件的时候,利用 ASM 动态的修改加载的 class 文件。Javaagent 是 java 命令的一个参数。参数 javaagent 可以用于指定一个 jar 包。

对该 Java 包有 2 个要求:

  • 这个 jar 包的 MANIFEST.MF 文件必须指定 Premain-Class
  • Premain-Class 指定的那个类必须实现 premain() 方法

premain 方法

  • 从字面上理解,就是运行在 main 函数之前的的类
  • 当 Java 虚拟机启动时,在执行 main 函数之前,JVM 会先运行 -javaagent 所指定 jar 包内 Premain-Class 这个类的 premain 方法

使用 JavaAgent

  • 创建一个 Premain-Class 指定的类,类中包含 premain 方法,方法逻辑由用户自己确定
  • 定义一个 MANIFEST.MF 文件,必须包含 Premain-Class 选项,通常也会加入 Can-Redefine-ClassesCan-Retransform-Classes 选项
  • premain 的类和 MANIFEST.MF 文件打成 jar 包,使用插件自动生成

MANIFEST.MF

  • Premain-Class:包含 premain 方法的类(类的全路径名)
  • Agent-Class:包含 agentmain 方法的类(类的全路径名)
  • Boot-Class-Path:设置引导类加载器搜索的路径列表。查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径。按列出的顺序搜索路径。列表中的路径由一个或多个空格分开。路径使用分层 URI 的路径组件语法。如果该路径以斜杠字符(“/”)开头,则为绝对路径,否则为相对路径。相对路径根据代理 JAR 文件的绝对路径解析。忽略格式不正确的路径和不存在的路径。如果代理是在 VM 启动之后某一时刻启动的,则忽略不表示 JAR 文件的路径(可选)
  • Can-Redefine-Classes:true 表示能重定义此代理所需的类,默认值为 false(可选)
  • Can-Retransform-Classes:true 表示能重转换此代理所需的类,默认值为 false(可选)
  • Can-Set-Native-Method-Prefix:true 表示能设置此代理所需的本机方法前缀,默认值为 false(可选)

使用参数 -javaagent: jar包路径, 启动要代理的方法。

快速入门

创建一个 Maven 工程:

添加依赖:

代码语言:html
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>top.it6666</groupId>
    <artifactId>JavaAgent</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <!--
                        自动添加 META-INF/MANIFEST.MF
                        -->
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <manifestEntries>
                            <Premain-Class>top.it6666.PreMainAgent</Premain-Class>
                            <Agent-Class>top.it6666.PreMainAgent</Agent-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

创建包, 在包中创建 PreMainAgent.java

代码语言:java
复制
/**
 * @author yby6
 **/
public class PreMainAgent {

    /**
     * 1、agentArgs 是 premain 函数得到的程序参数,随同 “– javaagent”一起传入。
     * 与 main函数不同的是,
     * 这个参数是一个字符串而不是一个字符串数组
     * 2、Inst 是一个 java.lang.instrument.Instrumentation 的实例,
     * 由 JVM 自动传入
     * java.lang.instrument.Instrumentation 是 instrument 包中定义的一个接口,
     * 也是这个包的核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作等等。
     **/
    public static void premain (String agentArgs, Instrumentation inst) {
        System.out.println ("========= premain方法执行1 ========");
        System.out.println (agentArgs);
    }

    /**
     * 如果不存在 premain(String agentArgs, Instrumentation inst)
     * 则会执行 premain(String agentArgs)
     */
    public static void premain (String agentArgs) {
        System.out.println ("========= premain方法执行2 ========");
        System.out.println (agentArgs);
    }
}

使用 maven 的 package 命令进行打包:

测试

创建 TestMain.java 测试类:记得编译一下搞到字节码

代码语言:java
复制
/**
 * @author yby6
 **/
public class TestMain {
    public static void main (String[] args) {
        System.out.println ("hello world");
    }
}

在启动的时候, 配置 JavaAgent 参数,拷贝刚刚打包好的 jar 包的绝对路径:

配置参数:

配置的 JVM 的参数,新版本的 IDEA 需要开启这个配置如下图:

代码语言:text
复制
-javaagent:D:\Develop\IDEAPro\JavaAgent\target\JavaAgent-1.0-SNAPSHOT.jar=test

运行 TestMain.java 最终效果如下图所示:

最后

本期结束咱们下次再见?~

? 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ ?

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • premain 方法
  • 使用 JavaAgent
    • MANIFEST.MF
    • 快速入门
      • 测试
      • 最后
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
      http://www.vxiaotou.com