byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

[question] How can replace field access with another class?

Open lucas-myx opened this issue 1 year ago • 2 comments

@raphw Sorry to inflict myself on you again like this!
as shown in the question, I encountered a problem while using MemberSubstitution to replace field A.foo access with another class B.bar() , as follows:

public class A {
    public String foo;
    public String foo() {
        return foo; // 'return B.bar()' after replaced
    }
}
public class B {
    public static String bar() {
        return "bar";
    }
}

an exception was thrown while executing the following code:

new ByteBuddy()
        .redefine(A.class)
        .visit(MemberSubstitution.relaxed()
                .field(named("foo"))
                .onRead()
                .replaceWith(B.class.getDeclaredMethod("bar"))
                .on(named("foo")))
        .make();

exception:

java.lang.IllegalStateException: Cannot invoke public static java.lang.String net.bytebuddy.asm.B.bar() on 1 parameters
	at net.bytebuddy.asm.MemberSubstitution$Substitution$ForMethodInvocation.resolve(MemberSubstitution.java:1266)

if field foo is static, there is no problem, but I understand that there should be no restriction on replacing with a static method, as long as the type and variable returned by the bar method are consistent?

I'm not very familiar with it, please correct me. Thank you very much!

lucas-myx avatar Aug 02 '24 16:08 lucas-myx

You cannot make a direct replacement of this field access with a static method. The field can be seen as a read on this. With a direct replacement, it would expect the same. You can however use a chain where you have more flexibility. Instead of using replaceWith, you use:

.replaceWithChain(
  new MemberSubstitution.Substitution.Chain.Step.ForInvocation.Factory(
    B.class.getDeclaredMethod("bar")
  )
)

It's called a chain because you can add multiple replacement instructions. In a chain the arguments to a replaced instruction (like this to a field read) are stored in the local variable array. This is why you can apply a substitution that takes different arguments.

raphw avatar Aug 05 '24 20:08 raphw

Thank you very much for taking the time to reply! I found a similar usage in your Unit test: MemberSubstitutionTest.java
which was written in great detail, I need to learn more about it. Thanks again!

lucas-myx avatar Aug 06 '24 02:08 lucas-myx