简体   繁体   中英

@Override doesn't work when using ByteBuddy disableClassFormatChanges

I am writing a java agent and I faced a pretty interesting issue that happens for me when I use Byte Buddy with the following option:

net.bytebuddy.agent.builder.AgentBuilder#disableClassFormatChanges

The issue is that it doesn't matter whether I override method of super class or not in a child of superclass, the one from superclass is always invoked.

Agent:

public class Main {


public static void premain(String agentOps, Instrumentation inst) {
    instrument(agentOps, inst);
}

public static void agentmain(String agentOps, Instrumentation inst) {
    instrument(agentOps, inst);
}

private static void instrument(String agentOps, Instrumentation inst) {
    new AgentBuilder.Default().with(new Eager())
            .disableClassFormatChanges()
            .type((any()))
            .transform((builder, typeDescription, classLoader, module) ->
                    builder.method(any()).intercept(Advice.to(LoggingAdvice.class)))
            .installOn(inst);
}

public static class LoggingAdvice {
    @Advice.OnMethodEnter
    static void enter(@Advice.Origin String method) {
    }

    @Advice.OnMethodExit
    static void exit(@Advice.Origin String method) {
    }
}

}

And classes that I use for testing:

Super:

public class Test1 {

public void test() {
    System.out.println("Test 1");
}

}

Child:

public class Test2 extends Test1 {

@Override
public void test() {
    System.out.println("Test 2");
}

}

Main class:

public class Main {

public static void main(String[] args) {
    new Test1().test();
    new Test2().test();
}

}

The result is:

Test 1
Test 1

Expected result:

Test 1
Test 2

Without an agent, everything works as expected.
I tried to play with ElementMatcher, but it didn't give successful results.

What might be the problem here?

Answer

I think issue there in your configuration.

Can you try please next one (similar to your one but without .disableClassFormatChanges() ):

  private static void instrument(String agentOps, Instrumentation inst) {
    new AgentBuilder.Default()
        .with(new Eager())
        .type((any()))
        .transform((builder, typeDescription, classLoader, module) ->
            builder
                .method(any())
                .intercept(Advice.to(LoggingAdvice.class)))
        .installOn(inst);
  }

PS

to make more clear cycle you can use tracking your calls for example

  @Advice.OnMethodEnter
  static void enter(@Advice.Origin String method) {
    System.out.println("enter");
  }

  @Advice.OnMethodExit
  static void exit(@Advice.Origin String method) {
    System.out.println("exit");
  }

possible can be useful useful to track instance where method was called.

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