Description
- Tried to execute my Groovy 3 to Groovy 4 performance degradation test case (see GROOVY-10307)
- Code worked with Groovy 4.0.0-RC1, but Groovy 4.0.0 throws RTE:
java.lang.VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface.
- Standalone test to reproduce error upcoming
- The error occurs when trying to access a class that represents a concrete database table, deriving from a shared database table base class with certain shared properties/methods added through a hierarchy of Groovy traits, with the properties/methods also occuring in interfaces implemented through said traits
- The error only occurs if that class is @CompileStatic annotated
- The error reported seems to be non-deterministically picked from any of the traits' properties/methods
- Full error:
java.lang.VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface. Exception Details: Location: Goo.GooTrait2trait$super$getNecessaryMember()Ljava/lang/String; @37: invokespecial Reason: Error exists in the bytecode Bytecode: 0000000: 2ac1 0042 9900 202a ba00 5000 00b9 0054 0000010: 0100 1255 03bd 0004 b800 5bba 005e 0000 0000020: b000 00bf 2ab7 0062 b0 Stackmap Table: full_frame(@33,{},{Object[#100]}) append_frame(@36,Object[#2])
- Stacktrace starting with JUnit 4 test invocation:
at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3137) at java.base/java.lang.Class.getDeclaredConstructors(Class.java:2357) at org.codehaus.groovy.reflection.CachedClass$2.lambda$initValue$4(CachedClass.java:69) at java.base/java.security.AccessController.doPrivileged(Native Method) at org.codehaus.groovy.vmplugin.v8.Java8.doPrivileged(Java8.java:628) at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:74) at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:64) at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:50) at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:37) at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:258) at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:232) at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:242) at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:166) at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:156) at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:139) at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:271) at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:314) at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:269) at org.codehaus.groovy.vmplugin.v8.Selector$MethodSelector.getMetaClass(Selector.java:575) at org.codehaus.groovy.vmplugin.v8.Selector$MethodSelector.setCallSiteTarget(Selector.java:1006) at org.codehaus.groovy.vmplugin.v8.IndyInterface.fallback(IndyInterface.java:351) at org.codehaus.groovy.vmplugin.v8.IndyInterface.access$000(IndyInterface.java:49) at org.codehaus.groovy.vmplugin.v8.IndyInterface$FallbackSupplier.get(IndyInterface.java:281) at org.codehaus.groovy.vmplugin.v8.IndyInterface.lambda$fromCache$1(IndyInterface.java:301) at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1133) at org.codehaus.groovy.vmplugin.v8.CacheableCallSite.getAndPut(CacheableCallSite.java:61) at org.codehaus.groovy.vmplugin.v8.IndyInterface.lambda$fromCache$2(IndyInterface.java:298) at org.codehaus.groovy.vmplugin.v8.IndyInterface.doWithCallSite(IndyInterface.java:367) at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:295) at ConsoleScript2.interfaceMethodIsIndirectSuperinterfaceBugTest(ConsoleScript2:15) at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:318) at ConsoleScript2.run(ConsoleScript2:18) at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:259) at groovy.lang.GroovyShell.run(GroovyShell.java:365) at groovy.lang.GroovyShell.run(GroovyShell.java:344) at groovy.lang.GroovyShell.run(GroovyShell.java:170) at groovy.console.ui.Console$GroovySourceType.run(Console.groovy:1174) at groovy.console.ui.Console.doRun(Console.groovy:1406) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:342) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:63) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:203) at groovy.console.ui.Console$_runScriptImpl_closure21.doCall(Console.groovy:1364) at groovy.console.ui.Console$_runScriptImpl_closure21.doCall(Console.groovy) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:279) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1009) at groovy.lang.Closure.call(Closure.java:418) at groovy.lang.Closure.call(Closure.java:412) at groovy.lang.Closure.run(Closure.java:500) at java.base/java.lang.Thread.run(Thread.java:834)
- Test case:
import org.junit.Test @groovy.transform.CompileStatic class Goo implements GooTrait1 {} trait GooTrait1 implements GooTrait2, GooInterface {} trait GooTrait2 { final String necessaryMember = "abc" } interface GooInterface {} @Test void interfaceMethodIsIndirectSuperinterfaceBugTest() { // java.lang.VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface. final Class clazz = Goo println clazz.name } interfaceMethodIsIndirectSuperinterfaceBugTest()