0

Goal

I would like to create a plug-in wrapper to embed a Java code that will let me enable/disable methods annotated with JUnit5 Before* and After* annotations at runtime as well as handle in similar manner JUnit5 extensions (the ExtendWith annotation).

I chose ByteBuddy as primary instrumentation library.

I created a github repo here: https://github.com/azewiusz/bytebuddy_examples where I describe the idea in more detail.

Question

The problem is that I cannot get instrumentation working for inner classes. I keep getting two exceptions:

Caused by: java.lang.IllegalStateException: Failed to invoke proxy for public abstract java.lang.reflect.AnnotatedElement net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$Executable.getAnnotatedReceiverType(java.lang.Object)

preceded by

Caused by: java.lang.IncompatibleClassChangeError tests.TestSetWithInnerClasses and tests.TestSetWithInnerClasses$HelperTestFilteredOutExtendWithInnerClass disagree on InnerClasses attribute

A test class that reproduces is here: https://github.com/azewiusz/bytebuddy_examples/blob/master/src/test/java/tests/CoreInstrumentationTest.java

-> Look there for test2

It fails at this transformation:

final Class strippedOffExtendWithAnnotation = filterOutJUnit5ExtendWithAnnotation(
testClass, classLoader );

Class beforeAll = stagedTypeTransform( strippedOffExtendWithAnnotation,
                new ByteBuddy().rebase( strippedOffExtendWithAnnotation,
                                ClassFileLocator.ForClassLoader.of( classLoader ) )
                        .name( testClass.getName() + "BeforeAll" )
                        .method( ElementMatchers
                        .isAnnotatedWith( BeforeAll.class ) )
                        .intercept( MethodDelegation.to( InterceptorForBeforeAllAnnotation.class ) ).make() );

I found following that seem to refer to similar problem:

But haven't found yet an exact solution.

1 Answers1

0

Instrumenting inner classes is tricky. Java classes contain so-called inner class attributes that describe Java class properties that compiled Java classes cannot represent. For example, a compiled Java class cannot be private, but you would still want to see this modifier for the inner class when using reflection.

You can consider to make your new class a top-level class by using topLevelType() in the DSL. You should also consider noNestMate() to avoid clashes there.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192