You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Byte Buddy中无法向Advice传递Method对象的技术问题

JDK21下Byte Buddy Advice注入Method对象失败的解决方案

问题场景

在JDK21环境搭配最新版Byte Buddy时,编写如下TimingAdvice类,尝试通过@Advice.Origin注入Method对象到方法进入逻辑中:

package plugin;

import java.lang.reflect.Method;
import net.bytebuddy.asm.Advice;

public class TimingAdvice {
  @Advice.OnMethodEnter
  public static void onEnter(@Advice.Origin Method method)
      throws Throwable {
    System.out.println("method: " + method);
  }
}

转换SomeAdvisedClass类时触发报错:

Failed to transform class SomeAdvisedClass: [java.lang.IllegalStateException: Cannot map this reference for static method or constructor start: public SomeAdvisedClass()].

改为注入类型名和方法名字符串后代码可正常运行,但业务需要获取Method对象以检查参数上的注解,需解决该问题。

报错原因

报错核心原因是Advice规则匹配到了目标类的构造方法,而构造方法对应的反射类型是Constructor而非Method,直接注入Method会导致类型不匹配,触发映射异常。

解决方案

方案一:过滤构造方法,仅匹配普通方法

修改Byte Buddy的匹配规则,排除构造方法,让Advice只作用于普通方法。以Plugin实现为例:

public class TimingPlugin implements Plugin {
  @Override
  public void apply(Plugin.Builder builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) {
    builder.visit(Advice.to(TimingAdvice.class)
        .on(not(isConstructor()))); // 排除构造方法,仅匹配普通方法
  }

  @Override
  public boolean matches(TypeDescription target) {
    // 按需定义目标类匹配规则
    return target.getName().equals("SomeAdvisedClass");
  }

  @Override
  public void close() throws IOException {}
}

此时原TimingAdvice的代码可正常运行,Method对象能正确注入。

方案二:兼容构造方法与普通方法,注入父类Executable

如果需要同时处理构造方法和普通方法,可注入Executable类型(Method和Constructor的共同父类),在代码中区分类型处理:

package plugin;

import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import net.bytebuddy.asm.Advice;

public class TimingAdvice {
  @Advice.OnMethodEnter
  public static void onEnter(@Advice.Origin Executable executable)
      throws Throwable {
    if (executable instanceof Method method) {
      // 处理普通方法,检查参数注解
      System.out.println("method: " + method);
      // 示例:遍历并打印参数注解
      for (int i = 0; i < method.getParameterCount(); i++) {
        System.out.println("参数" + i + "的注解列表:" + method.getParameterAnnotations()[i]);
      }
    }
    // 如需处理构造方法,可添加else分支
  }
}

这种方式能覆盖所有可执行元素,同时满足获取方法对象检查参数注解的需求。

内容的提问来源于stack exchange,提问作者John Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 04:31:11