java - ByteBuddy - 修改加载类的默认值

标签 java bytecode byte-buddy

我正在尝试更改已加载类的方法的返回值。

从 ByteBuddy 的文档 ( http://bytebuddy.net/#/tutorial ) 来看,只要我不添加任何字段/方法,这似乎可以使用 Java 代理实现。

我的代码如下:

ByteBuddyAgent.install();

new ByteBuddy()
        .redefine(StuffImpl.class)
        .method(returns(Result.class))
        .intercept(FixedValue.value(new Result("intercepted")))
        .make()
        .load(StuffImpl.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

但我遇到以下异常:

java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)

问题是,我没有添加任何方法。上述代码中Byte Buddy在哪里添加了字段或方法?

编辑:

public class StuffImpl {

    public Result validate() {
        return new Result("original");
    }
}

public class Result {

    private String result;

    public Result(String result) {
        this.result = result;
    }
}

最佳答案

您定义一个委托(delegate)给 Byte Buddy 需要存储在某处的固定值new Result("intercepted")FixedValue 实现为您创建一个静态字段,以便生成的方法可以从中读取您的值。您可以通过避免使用 FixedValue 来以不同的方式解决此问题,例如:

  1. 委托(delegate)给另一个保存字段值的类(保留引用标识)。

    MethodDelegation.to(Holder.class);
    class Holder {
      static Result result = new Result("intercepted");
      static Result intercept() { return result; }
    }
    

    这是最通用的方法,您当然可以直接从该方法返回new Result("intercepted")

  2. 动态创建实例:

    MethodCall.construct(Result.class.getDeclaredConstructor(String.class))
              .with("intercepted");
    

    在这种情况下,“intercepted”字符串不需要存储在字段中,因为它可以在类的常量池中引用(对于原始值也是如此)。


您的StuffImpl可能定义了一个静态初始值设定项。此初始值设定项由 Byte Buddy 分解为私有(private)方法,以便可以向其中添加其他语句。

您可以通过设置禁用此行为:

new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE);

这确实应该在文档中,我将在下一个版本中添加它。

关于java - ByteBuddy - 修改加载类的默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35066822/

相关文章:

java - 希望在 Java Web 应用程序中集成/嵌入聊天客户端

java - 从列表中获取任何元素

python - 已编译脚本的字节码因编译方式而异

java - Byte Buddy - 带 ByteBuddyAgent 的 HotSwap

java - 如何拦截构造函数

java - 重新定义非静态方法

java - JSON 对象不正确并导致 HttpException

java - eclipse默认的jpa实现库哪里下载?

java - 堆叠 ASM 访问者的正确方法是什么?

java - 在byte buddy的MethodDelegation中高效获取调用者