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

ByteBuddy拦截方法中使用MethodCall调用可变长参数方法如何传入多个字段

错误根因

Arrays.asList()的可变参数是Java语法糖,实际字节码层面的方法签名是public static List asList(Object[]),仅接收1个数组类型参数。你直接调用withField("a", "b")会尝试向该方法传递2个int类型参数,自然出现参数不匹配异常,同时int基本类型需要装箱为Integer才能存入Object数组。

可行实现方案

方案1:使用Advice实现(更简洁易维护,推荐)

ByteBuddy的Advice机制可以直接写Java代码实现逻辑,不需要手动拼接方法调用参数,适配性更强:
首先定义Advice切面类:

public class GetFieldsAdvice {
    @Advice.OnMethodExit
    public static void intercept(@Advice.This TestClass instance, @Advice.Return(readOnly = false) List<?> result) {
        // 直接编写业务逻辑,自动处理装箱、可变参数
        result = Arrays.asList(instance.a, instance.b);
    }
}

修改ByteBuddy实现代码:

new ByteBuddy()
    .rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(), 
            ClassFileLocator.ForClassLoader.ofSystemLoader())
    .method(ElementMatchers.named("getFields"))
    .intercept(Advice.to(GetFieldsAdvice.class))
    .make()
    .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
    .getLoaded();

方案2:继续使用MethodCall,适配可变参数规则

如果要保留MethodCall的实现方式,需要添加asVarArgs()配置自动打包参数为数组,同时手动处理基本类型装箱:

new ByteBuddy()
    .rebase(TypePool.Default.ofSystemLoader().describe("com.test.TestClass").resolve(), 
            ClassFileLocator.ForClassLoader.ofSystemLoader())
    .method(ElementMatchers.named("getFields"))
    .intercept(MethodCall.invoke(Arrays.class.getMethod("asList", Object[].class))
            .withField("a").as(Integer.class)
            .withField("b").as(Integer.class)
            .asVarArgs()) // 自动将多个参数包装为Object数组传入可变参数方法
    .make()
    .load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION)
    .getLoaded();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:57:05