gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 08:41:30 26 4
gpt4 key购买 nike

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

从 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)

问题是,我没有添加任何方法。字节好友在上面的代码哪里添加了字段或者方法?

编辑:

public class StuffImpl {

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

public class Result {

private String result;

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

最佳答案

您定义一个固定值 new Result("intercepted") 的委托(delegate),Byte Buddy 需要将其存储在某处。 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com