ByteBuddy - 修改load class的默认值
ByteBuddy - Modify load class's default value
我正在尝试更改已加载的方法的 return 值 class。
从 ByteBuddy 的文档 (http://bytebuddy.net/#/tutorial) 这似乎可以使用 Java 代理,只要我不添加任何 field/method.
我的代码如下:
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")
的委托,Byte Buddy 需要将其存储在某个地方。 FixedValue
实现为您创建一个静态字段,以便生成的方法可以从中读取您的值。您可以通过避免 FixedValue
以不同的方式解决这个问题,例如:
委托给另一个 class 保存字段中的值(保留引用标识)。
MethodDelegation.to(Holder.class);
class Holder {
static Result result = new Result("intercepted");
static Result intercept() { return result; }
}
这是最通用的方法,你当然可以returnnew Result("intercepted")
直接从方法中获取。
动态创建实例:
MethodCall.construct(Result.class.getDeclaredConstructor(String.class))
.with("intercepted");
在这种情况下,"intercepted"
字符串不需要存储在字段中,因为它可以在class的常量池中被引用(原始值也是如此)。
您的 StuffImpl
可能定义了静态初始值设定项。这个初始化器被 Byte Buddy 分解成一个 private
方法,这样它就可以向它添加额外的语句。
您可以通过设置禁用此行为:
new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE);
这确实应该在文档中,我会在下一个版本中添加它。
我正在尝试更改已加载的方法的 return 值 class。
从 ByteBuddy 的文档 (http://bytebuddy.net/#/tutorial) 这似乎可以使用 Java 代理,只要我不添加任何 field/method.
我的代码如下:
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")
的委托,Byte Buddy 需要将其存储在某个地方。 FixedValue
实现为您创建一个静态字段,以便生成的方法可以从中读取您的值。您可以通过避免 FixedValue
以不同的方式解决这个问题,例如:
委托给另一个 class 保存字段中的值(保留引用标识)。
MethodDelegation.to(Holder.class); class Holder { static Result result = new Result("intercepted"); static Result intercept() { return result; } }
这是最通用的方法,你当然可以return
new Result("intercepted")
直接从方法中获取。动态创建实例:
MethodCall.construct(Result.class.getDeclaredConstructor(String.class)) .with("intercepted");
在这种情况下,
"intercepted"
字符串不需要存储在字段中,因为它可以在class的常量池中被引用(原始值也是如此)。
您的 StuffImpl
可能定义了静态初始值设定项。这个初始化器被 Byte Buddy 分解成一个 private
方法,这样它就可以向它添加额外的语句。
您可以通过设置禁用此行为:
new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE);
这确实应该在文档中,我会在下一个版本中添加它。