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

[Question] Why would a new field var2 be added after replace field access with method?

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

@raphw First of all, thank you for your previous response. The issue has been resolved. Thank you!

I found use MemberSubstitution to replace field A.foo access with B.bar() , will add a new field var2 in the decompiled bytecode file, as follows:

public class A {
    public String foo;
    public String foo() {
        return foo; // 'return B.bar()' after replaced
    }
}
public class B {
    public Object bar(@CustomFiled String foo, @CustomRetunType Class<?> returnType) {
       if (String.class.isAssignableFrom(returnType)) {
            return "bar";
        }
        return null;
    }
}

MemberSubstitution usage:

new ByteBuddy().redefine(Foo.class)
                    .visit(MemberSubstitution.relaxed()
                    .field(named("foo"))
                    .onRead()
                    .replaceWithChain(
                            MemberSubstitution.Substitution.Chain.Step.ForDelegation.withCustomMapping()
                                    .bind(CustomFiled.class, fooFieldDescription)
                                    .bind(CustomRetunType.class, fieldDescription.getType().asErasure())
                                    .to(B.class.getDeclaredMethod("bar"),
                            MemberSubstitution.Substitution.Chain.Step.ForAssignment.castToSubstitutionResult())
                    .on(any()))).make().saveIn(file);

open the decompiled A.class bytecode file, as follows:

public String foo() {
    Object var2 = null; // new add field
     return (String)B.bar(this.foo, String.class);
}

I don't understand why we need to add a new field var2 and what its purpose is? (I'm worried that the extra fields may have other additional impacts)

I guess it might be due to my incorrect usage, please correct me. Thank you very much!

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

If a chain is used, all arguments are temporarily stored as local variable. This is expected and will likely be ignored by the JIT, nothing to worry about.

If you want to write custom byte code, you can avoid it by implementing your own handler and avoid the chain. There's also some ready made ones.

raphw avatar Aug 17 '24 14:08 raphw

Thank you for your reply! one more question, Is there such an example: implementing your own handler and avoid the chain? Thank you!

lucas-myx avatar Aug 19 '24 14:08 lucas-myx

Yes, any other method implements such a handler, the chain method also offers a handler implementation itself. If you look at the source, you will be able to see how this looks like.

raphw avatar Aug 19 '24 21:08 raphw