Search code examples
byte-buddy

ByteBuddy: AbstractMethodError when set interceptor


The following is my learning code, when I executing the code, an exception happened:

Exception in thread "main"
java.lang.AbstractMethodError: org.learning.UserRepository$ByteBuddy$etz0xUhc.$$_pharos_set_interceptor(Lorg/learning/Interceptor;)V**

ByteBuddy version: 1.10.14

final TypeCache.SimpleKey cacheKey = getCacheKey(learningClazz, interceptor.getClass());
Class proxyClass = load(learningClazz, proxyCache, cacheKey, byteBuddy ->
  byteBuddy
    .subclass(learningClazz)
    .defineField(ProxyConfiguration.INTERCEPTOR_FIELD_NAME, Interceptor.class, Visibility.PRIVATE)
    .method(not(isDeclaredBy(Object.class)))
    .intercept(MethodDelegation.to(ProxyConfiguration.InterceptorDispatcher.class))
    .implement(ProxyConfiguration.class)
    .intercept(FieldAccessor.ofField(ProxyConfiguration.INTERCEPTOR_FIELD_NAME)
    .withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC)));

final ProxyConfiguration proxy = (ProxyConfiguration) proxyClass.getDeclaredConstructor().newInstance();
proxy.$$_pharos_set_interceptor(interceptor);
return (T) proxy;
public interface ProxyConfiguration {

  String INTERCEPTOR_FIELD_NAME = "$$_pharos_interceptor";

  void $$_pharos_set_interceptor(Interceptor interceptor);

  class InterceptorDispatcher {
    @RuntimeType
    public static Object intercept(
      @This final Object instance,
      @Origin final Method method,
      @AllArguments final Object[] arguments,
      @StubValue final Object stubValue,
      @FieldValue(INTERCEPTOR_FIELD_NAME) Interceptor interceptor,
      @SuperMethod Method superMethod
    ) throws Throwable
    {
      if (interceptor == null) {
        return stubValue;
      }
      else {
        return interceptor.intercept(instance, method, arguments, superMethod);
      }
    }
  }
  
}

Solution

  • Package-private methods are overriden but the JVM will not dispatch them dynamically if the subclass is loaded on a different class loader. If you declare the method public, the problem should be solved. Alternatively, inject the class into the target class loader.