bytebuddy实现javaagent之拦截实例方法

554 阅读2分钟

使用 Byte Buddy 实现 Java Agent 来拦截实例方法,可以通过以下步骤实现。我们将创建一个 Java Agent,使用 Byte Buddy 来拦截某个类的实例方法,并在方法调用前后执行一些逻辑。

步骤 1:创建 Java Agent

首先,我们需要创建一个 Java Agent。一个 Java Agent 需要实现一个 premain 方法,该方法将在 JVM 启动时执行。

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.instrument.Instrumentation;

public class MyAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        new AgentBuilder.Default()
            .type(ElementMatchers.nameContains("TargetClass")) // 拦截目标类
            .transform((builder, typeDescription, classLoader, module) -> 
                builder.method(ElementMatchers.named("targetMethod")) // 拦截目标方法
                       .intercept(Advice.to(MyAdvice.class)) // 使用 Advice 类进行拦截
            ).installOn(inst);
    }
}

步骤 2:创建 Advice 类

Advice 类用于定义在方法调用前后执行的逻辑。我们可以在 @OnMethodEnter@OnMethodExit 注解的方法中编写这些逻辑。

import net.bytebuddy.asm.Advice;

public class MyAdvice {
    @Advice.OnMethodEnter
    public static void onEnter(@Advice.Origin String method) {
        System.out.println("Entering method: " + method);
    }

    @Advice.OnMethodExit
    public static void onExit(@Advice.Origin String method) {
        System.out.println("Exiting method: " + method);
    }
}

步骤 3:打包和运行

  1. 打包:将 MyAgentMyAdvice 类打包成一个 JAR 文件,并在 MANIFEST.MF 文件中指定 Premain-Class

    MANIFEST.MF 文件内容:

    Manifest-Version: 1.0
    Premain-Class: MyAgent
    

    使用以下命令打包:

    jar cmf MANIFEST.MF myagent.jar MyAgent.class MyAdvice.class
    
  2. 运行:使用 -javaagent 选项运行目标应用程序,并指定生成的 JAR 文件。

    java -javaagent:myagent.jar -cp target_application.jar com.example.Main
    

示例目标类

为了测试,我们可以创建一个简单的目标类和方法。

public class TargetClass {
    public void targetMethod() {
        System.out.println("Inside target method.");
    }

    public static void main(String[] args) {
        new TargetClass().targetMethod();
    }
}

运行结果

当我们运行目标应用程序时,应该可以看到如下输出:

Entering method: public void TargetClass.targetMethod()
Inside target method.
Exiting method: public void TargetClass.targetMethod()

详细解释

  1. AgentBuilder:用于定义和配置 Java Agent。我们使用 type 方法来指定要拦截的类,使用 transform 方法来定义如何拦截方法。
  2. ElementMatchers:用于匹配类和方法。nameContainsnamed 方法用于匹配类名和方法名。
  3. Advice:用于在方法调用前后执行逻辑。@OnMethodEnter 注解的方法将在目标方法进入时执行,@OnMethodExit 注解的方法将在目标方法退出时执行。
  4. 打包和运行:将 Agent 类和 Advice 类打包成一个 JAR 文件,并在运行目标应用程序时使用 -javaagent 选项指定该 JAR 文件。

通过以上步骤,我们可以使用 Byte Buddy 实现一个 Java Agent 来拦截实例方法,并在方法调用前后执行自定义逻辑。

牛皮参考: www.cnblogs.com/crazymakerc…

www.liuhaihua.cn/archives/56…