Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redefine non-static methods

I try to redefine simple non-static method but I get an exception:

Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)

Classes:

class Source { 
  def hello(name: String): String = "" 
}

class Target {
  def hello(name: String): String = "Hello" + name + "!"
}

Call:

 new ByteBuddy()
      .rebase(classOf[Source])
      .method(ElementMatchers.named("hello"))
      .intercept(MethodDelegation.to(new Target))
      .make()
      .load(classOf[Source].getClassLoader, ClassReloadingStrategy.fromInstalledAgent())
      .getLoaded
      .newInstance()
      .hello("World")

Classes above are scala classes but they compile to standard java classes.

How to redefine method correctly?

like image 697
nigredo Avatar asked Mar 12 '26 11:03

nigredo


1 Answers

What you are trying to to is currently not supported by the JVM, you cannot add or remove fields or methods from any class what is an implict consequence of rebasing.

What you can do instead is redefining a class with ByteBuddy::redefine. This way, Byte Buddy replaces the original implementation instead of retaining it for potential invocation. In order to make this work, you also need to delegate to a stateless (startic) method as follows:

public class Target {
  public static String hello() {
    return "Hello" + name + "!"
  }
}

with a delegation: MethodDelegation.to(Target.class). This is necessary because otherwise, Byte Buddy would need to add a field to the instrumented class to store the delegation instance what is impossible with redefinition.

Alternatively, have a look at the Advice class which allows you to inline code what is compatible to rebasement where the original implementation is retained.

like image 105
Rafael Winterhalter Avatar answered Mar 15 '26 02:03

Rafael Winterhalter