Search code examples
javabyte-buddy

Why isn't my ByteBuddy interceptor called?


I'm trying to intercept calls to JavaFX' ScenePulseListener.pulse() method using ByteBuddy 1.4.26.

The following code seems to properly refer to this class and method, and the interceptor's method signature seems to be correct, as tampering with that properly triggers exceptions.

(installJavaFXPulseInterceptor() is called before the ScenePulseListener class is loaded.)

However, the interceptor method is never called when ScenePulseListener.pulse() is : what am I doing wrong ?

public static class PulseInterceptor
{
    public static void interceptPulse( @SuperCall final Callable< Void >  pSuper )
        throws Exception
    {
        pSuper.call();
    }
}

public static final void installJavaFXPulseInterceptor()
{
    final TypePool            type_pool= TypePool.Default.ofClassPath();

    (new ByteBuddy())
        .rebase( type_pool.describe( "javafx.scene.Scene$ScenePulseListener" ).resolve(),
                 ForClassLoader.ofClassPath() )
        .method( named( "pulse" ) )
        .intercept( MethodDelegation.to( PulseInterceptor.class ) )
        .make()
        .load( ClassLoader.getSystemClassLoader(), ClassLoadingStrategy.Default.INJECTION );
}

Solution

  • You should not use this approach as you cannot guarantee that the class is not yet loaded when you are trying to inject the type. This practically only works when nothing is loaded prior to your code, i.e. directly after the main method is invoked.

    Ideally, you should define a Java agent for such transformations.

    You can validate your interceptor by defining a class:

    public class Foo {
      public void pulse() {
        System.out.println("foo");
      }
    }
    

    And see if your transformation works on it. Make sure to not load the class prior to transformation. Doing this on my machine, demonstrates that your code example is already loaded.

    Are you sure the system class loader is loading your JavaFx class in question? What does Pulse.class.getClassLoader() say?