简体   繁体   中英

ByteBuddy not redefining static method

I am trying to redefine 2 methods using ByteBuddy, like so:

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();
}

The direct call to CppBlockInterceptor produces the intended output, but the call to the method that was supposed to be replaced still uses the old behavior. Is there any reason for this?

Your CommandBase class is already loaded before you get the chance to redefine it. Byte Buddy cannot replace a loaded class without using a Java agent. Try running this:

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

without explicitly referrencing CommandBase before the invocation and it will work. Better would be to use an AgentBuilder and a Java agent, though. The documentation of Byte Buddy explains why .

The accepted answer is not longer compilable (not surprising since more than 5 years have passed). The correct code using Byte Buddy v1.10.17 is as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM