Uploaded image for project: 'Magnolia'
  1. Magnolia
  2. MAGNOLIA-8958

Guice method interceptions fails with "Unsupported class file major version 61" on JRE 17

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Neutral Neutral
    • 6.2.37
    • 6.2.35
    • None
    • Yes
    • Yes
    • Yes

      Steps to reproduce

      public class InterceptorTest {
      
          interface Base<T>{
              void foo(T arg);
          }
      
          // Inheriting from a parametrized base class causes the JVM to generate a bridge method, which in
          // turn will trigger the code path in bindInterceptor() that leads to the problem.
          public static class Impl implements Base<String > {
              @Override
              public void foo(String arg) { }
          }
      
          @Test
          void test() {
              Injector injector = Guice.createInjector(new AbstractModule() {
                  @Override
                  protected void configure() {
                      bindInterceptor(
                          Matchers.any(),
                          Matchers.any(),
                          invocation -> null
                      );
                      bind(Impl.class);
                  }
              });
          }
      }
      

      Compile and run InterceptorTest with Java 17.

      Note: it is not clear how to automate this test as Magnolia 6.2 does not compile and build against Java 17 currently.

      Expected results

      The test passes.

      Actual results

      The test fails:

      com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalArgumentException: Unsupported class file major version 61    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2051)
          at com.google.common.cache.LocalCache.get(LocalCache.java:3951)
          at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
          at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
          at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)
          at com.google.inject.internal.FailableCache.get(FailableCache.java:51)
          at com.google.inject.internal.ConstructorInjectorStore.get(ConstructorInjectorStore.java:48)
          at com.google.inject.internal.ConstructorBindingImpl.initialize(ConstructorBindingImpl.java:155)
          at com.google.inject.internal.InjectorImpl.initializeBinding(InjectorImpl.java:581)
          at com.google.inject.internal.AbstractBindingProcessor$Processor$1.run(AbstractBindingProcessor.java:176)
          at com.google.inject.internal.ProcessedBindingData.initializeBindings(ProcessedBindingData.java:49)
          at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:122)
          at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
          at com.google.inject.Guice.createInjector(Guice.java:87)
          at com.google.inject.Guice.createInjector(Guice.java:69)
          at com.google.inject.Guice.createInjector(Guice.java:59)
          at info.magnolia.addon.commons.cache.InterceptorTest.test(InterceptorTest.java:37)
          at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
          at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.base/java.lang.reflect.Method.invoke(Method.java:568)
          at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
          at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
          at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
          at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
          at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
          at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
          at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
          at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
          at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
          at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
          at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
          at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
          at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
          at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
          at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
          at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
          at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
          at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
          at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
          at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
          at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
          at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
          at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
          at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
          at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
          at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
          at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
          at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
          at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
          at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
          at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
          at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
          at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
          at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
          at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
          at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
      Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 61
          at com.google.inject.internal.asm.$ClassReader.<init>(ClassReader.java:184)
          at com.google.inject.internal.asm.$ClassReader.<init>(ClassReader.java:166)
          at com.google.inject.internal.asm.$ClassReader.<init>(ClassReader.java:152)
          at com.google.inject.internal.asm.$ClassReader.<init>(ClassReader.java:273)
          at com.google.inject.internal.cglib.core.$DuplicatesPredicate.<init>(DuplicatesPredicate.java:93)
          at com.google.inject.internal.cglib.proxy.$Enhancer.getMethods(Enhancer.java:557)
          at com.google.inject.internal.cglib.proxy.$Enhancer.getMethods(Enhancer.java:535)
          at com.google.inject.internal.ProxyFactory.<init>(ProxyFactory.java:87)
          at com.google.inject.internal.ConstructorInjectorStore.createConstructor(ConstructorInjectorStore.java:82)
          at com.google.inject.internal.ConstructorInjectorStore.access$000(ConstructorInjectorStore.java:29)
          at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:37)
          at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:33)
          at com.google.inject.internal.FailableCache$1.load(FailableCache.java:40)
          at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3529)
          at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2278)
          at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2155)
          at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2045)
          ... 81 more
       

      Workaround

      Use Java 11.

      Development notes

      • This happens to customer projects using @Cacheable annotations. See SUPPORT-16042 and this reproducer.
      • According to mgeljic  " if a customer successfully builds a module w/ 17 and puts it on the classpath, our runtime should support it, even if we ourselves are not building with 17."

      Root cause analysis

      The is caused by Guice 4.2.2's shaded version of asm not being compatible with Java 17. In ClassFileReader it checks the class file version and fails:

      if (checkClassVersion && this.readShort(classFileOffset + 6) > 58) {
          throw new IllegalArgumentException("Unsupported class file major version " + this.readShort(classFileOffset + 6)); 
      }

      To fix this we need to upgrade to Guice 5.1.0. See  DEV-2014 for the related effort on 6.3.

        Acceptance criteria

              mduerig Michael Duerig
              mduerig Michael Duerig
              Foundation
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved:
                Work Started: