raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.29k stars 807 forks source link

Intercept methods called inside other class methods with super.<method> #1558

Closed Gosstik closed 1 year ago

Gosstik commented 1 year ago

I'm new to Byte Buddy and can't understand how to intercept methods that are called inside class with super.. Could you please give example of how to do this with subclass?

class A {
    void commonMethod() {
        System.out.println("A: commonMethod");
    }
}

class B extends A {
    @Override
    void commonMethod() {
        super.commonMethod();
        System.out.println("B: commonMethod");
    }
}

I intercept methods with MethodDelegation to class with static method. Tried something like the following:

Class<?> proxyClass = ByteBuddy()
    .subclass(B.class)
    .method(ElementMatchers.any())
    .intercept(MethodDelegation.to(StaticInterceptor.class))
    .make()
    .load(B.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
    .getLoaded();

B b = proxyClass.getDeclaredConstructor().newInstance();

b.commonMethod();

but in that case interceptor is called only once for method B.commonMethod, but I want also intercept call super.commonMethod(). Thanks!

raphw commented 1 year ago

By subclassing B, you create a new class that overrides the method once more. You cannot intercept the super method call as it's happening within B.

If you want to intercept methods that way, normally you'd need to write a Java agent to redefine classes. Have a look into AgentBuilder and Advice.

This is a limitation set by the JVM. Think how you'd so things in Java otherwise, if you cannot write a class like it, Byte Buddy cannot normally avoid it.