初学JavaAgent

1,497 阅读2分钟

最近在学习JavaAgent,说一下学习的一些心得。

JavaAgent一种在加载类的时候,对字节码进行修改的技术,中文含义Java探针技术。

其原理:

JavaAgent是jdk1.5以后引入的技术,是一种在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件的JAVA代理技术。

image.png

创建agent

上代码: 第一步:创建一个class类,创建两个方法


import java.lang.instrument.Instrumentation;

/**
 * @author fade
 * @Title: MyAgent
 * @ProjectName my-agent
 * @Description: TODO
 * @date 2021/4/123:51 下午
 */
public class MyAgent {
    /**
     * 该方法在main方法之前运行,与main方法运行在同一个JVM中
     * 并被同一个System ClassLoader装载
     * 被统一的安全策略(security policy)和上下文(context)管理
     *
     * @param agentOps
     * @param inst
     * @author fade
     * @create  2021/4/123:51 下午
     */
    public static void premain(String agentOps, Instrumentation inst) {
        System.out.println("=========premain方法执行========");
        System.out.println(agentOps);
    }

    /**
     * 如果不存在 premain(String agentOps, Instrumentation inst)
     * 则会执行 premain(String agentOps)
     *
     * @param agentOps
     * @author fade
     * @create  2021/4/123:51 下午
     */
    public static void premain(String agentOps) {
        System.out.println("=========premain方法执行2========");
        System.out.println(agentOps);
    }

}

public static void agentmain(String args, Instrumentation inst)

public static void agentmain(String args)

方法。并且在二者同时存在时以前者优先。args和inst与premain中的一致。

第二步: 第一种方式(maven方式) pom文件中添加:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifestEntries>
                <Premain-Class>com.sage.agent.MyAgent</Premain-Class>
                <Agent-Class>com.sage.agent.MyAgent</Agent-Class>
                <Can-Redefine-Classes>true</Can-Redefine-Classes>
                <Can-Retransform-Classes>true</Can-Retransform-Classes>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Premain-Class 、Agent-Class指向agent的主类,即刚才创建的MyAgent。

第二种方式(配置文件方式) 在resource中创建并设置MANNIFEST.MF,指定Agent-Class:

Manifest-Version: 1.0
Agent-Class: com.sage.agent.MyAgent
Created-By: 1.6.0_29

一个简单的agent就实现了

如何加载 Java Agent

通过JVM参数 -javaagent:**.jar 启动,程序启动的时候,会优先加载Java Agent,并执行其 premain 方法,这个时候,其实大部分的类都还没有被加载,这个时候可以实现对新加载的类进行字节码修改,但是如果 premain 方法执行失败或抛出异常,那么JVM会被中止,这是很致命的问题。