ByteBuddy 没有重新定义静态方法
ByteBuddy not redefining static method
我正在尝试使用 ByteBuddy 重新定义 2 个方法,如下所示:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
ClassLoadingStrategy.Default classLoadingStrategy = ClassLoadingStrategy.Default.INJECTION;
new ByteBuddy().redefine(CommandBase.class).method(returns(Item.class)).intercept(MethodDelegation.to(CppItemInterceptor.class)).make().load(classLoader, classLoadingStrategy);
new ByteBuddy().redefine(CommandBase.class).method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class)).make().load(classLoader, classLoadingStrategy);
try {
System.out.println(CppBlockInterceptor.getBlockByText(null, "1").getLocalizedName());
System.out.println(CommandBase.getBlockByText(null, "1").getLocalizedName());
} catch (Exception e) {
e.printStackTrace();
}
对 CppBlockInterceptor 的直接调用产生了预期的输出,但对应该被替换的方法的调用仍然使用旧行为。这有什么原因吗?
您的 CommandBase
class 在您有机会重新定义它之前已经加载。 Byte Buddy 无法在不使用 Java 代理的情况下替换已加载的 class。尝试 运行 这个:
TypeDescription commandBase = new TypePool.Default.ofClassPath()
.locate("my.package.CommandBase");
new ByteBuddy()
.redefine(commandBase, ClassFileLocator.ForClassLoader.ofClassPath())
.method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTOR);
CppBlockInterceptor.getBlockByText(null, "1").getLocalizedName()
在调用之前没有明确引用 CommandBase
并且它会起作用。不过,最好使用 AgentBuilder
和 Java 代理。 documentation of Byte Buddy explains why.
已接受的答案不再可编译(不足为奇,因为已经过去了 5 年多)。使用字节好友v1.10.17的正确代码如下:
TypeDescription typeDescription = TypePool.Default.ofSystemLoader()
.describe("my.package.CommandBase")
.resolve();
new ByteBuddy()
.redefine(typeDescription, ClassFileLocator.ForClassLoader.ofSystemLoader())
.method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION);
我正在尝试使用 ByteBuddy 重新定义 2 个方法,如下所示:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
ClassLoadingStrategy.Default classLoadingStrategy = ClassLoadingStrategy.Default.INJECTION;
new ByteBuddy().redefine(CommandBase.class).method(returns(Item.class)).intercept(MethodDelegation.to(CppItemInterceptor.class)).make().load(classLoader, classLoadingStrategy);
new ByteBuddy().redefine(CommandBase.class).method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class)).make().load(classLoader, classLoadingStrategy);
try {
System.out.println(CppBlockInterceptor.getBlockByText(null, "1").getLocalizedName());
System.out.println(CommandBase.getBlockByText(null, "1").getLocalizedName());
} catch (Exception e) {
e.printStackTrace();
}
对 CppBlockInterceptor 的直接调用产生了预期的输出,但对应该被替换的方法的调用仍然使用旧行为。这有什么原因吗?
您的 CommandBase
class 在您有机会重新定义它之前已经加载。 Byte Buddy 无法在不使用 Java 代理的情况下替换已加载的 class。尝试 运行 这个:
TypeDescription commandBase = new TypePool.Default.ofClassPath()
.locate("my.package.CommandBase");
new ByteBuddy()
.redefine(commandBase, ClassFileLocator.ForClassLoader.ofClassPath())
.method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTOR);
CppBlockInterceptor.getBlockByText(null, "1").getLocalizedName()
在调用之前没有明确引用 CommandBase
并且它会起作用。不过,最好使用 AgentBuilder
和 Java 代理。 documentation of Byte Buddy explains why.
已接受的答案不再可编译(不足为奇,因为已经过去了 5 年多)。使用字节好友v1.10.17的正确代码如下:
TypeDescription typeDescription = TypePool.Default.ofSystemLoader()
.describe("my.package.CommandBase")
.resolve();
new ByteBuddy()
.redefine(typeDescription, ClassFileLocator.ForClassLoader.ofSystemLoader())
.method(returns(Block.class)).intercept(MethodDelegation.to(CppBlockInterceptor.class))
.make()
.load(ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION);