Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
3.0.6, 3.0.7
-
None
-
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)
Eclipse OpenJ9 VM (build openj9-0.21.0, JRE 1.8.0 Windows 10 amd64-64-Bit Compressed References 20200728_776 (JIT enabled, AOT enabled)
ASM 9.0
Description
Issue
With Groovy 3.0.6 (& 3.0.7), when embedding an outer field unary pre/postfix operation within a GString, combined with static compilation (@CompileStatic), the generated bytecode fails at class loading time (VerifyError)
package org.example import groovy.transform.CompileStatic import org.objectweb.asm.ClassReader import org.objectweb.asm.util.CheckClassAdapter @CompileStatic class OuterClass { int counter = 0 def call() { { -> "Hello${++counter}Bar" }.call() } static void main(String[] args) { CheckClassAdapter.verify(new ClassReader('org/example/OuterClass$_call_closure1'), true, new PrintWriter(System.err)) assert new OuterClass().call() == 'Hello1Bar' } }
HotSpot VM error
java.lang.VerifyError: Bad type on operand stack Exception Details: Location: org/example/OuterClass$_call_closure1.doCall()Ljava/lang/Object; @46: aastore Reason: Type integer (current frame, stack[4]) is not assignable to reference type Current Frame: bci: @46 flags: { } locals: { 'org/example/OuterClass$_call_closure1', integer } stack: { uninitialized 0, uninitialized 0, '[Ljava/lang/Object;', '[Ljava/lang/Object;', integer, integer, 'java/lang/Integer' } Bytecode: 0x0000000: bb00 1c59 04bd 001e 5903 2ac0 0002 b600 0x0000010: 2112 09b8 0027 c000 09b6 002b 0460 593c 0x0000020: 2ab6 002c c000 091b b800 30b8 0036 5305 0x0000030: bd00 3859 0312 3a53 5904 123c 53b7 003f 0x0000040: b000 bf Stackmap Table: full_frame(@65,{},{Object[#65]}) at org.example.OuterClass.call(OuterClass.groovy:12) at org.example.OuterClass.main(OuterClass.groovy:19)
OpenJ9 VM error
java.lang.VerifyError: JVMVRFY012 stack shape inconsistent; class=org/example/OuterClass$_call_closure1, method=doCall()Ljava/lang/Object;, pc=46 Exception Details: Location: org/example/OuterClass$_call_closure1.doCall()Ljava/lang/Object; @46: JBaastore Reason: Type 'java/lang/Integer' (current frame, stack[6]) is not assignable to 'java/lang/Object' Current Frame: bci: @46 flags: { } locals: { 'org/example/OuterClass$_call_closure1', integer } stack: { 'uninitialized', 'uninitialized', '[Ljava/lang/Object;', '[Ljava/lang/Object;', integer, integer, 'java/lang/Integer' } Stackmap Table: full_frame(@65,{},{Object[#19]}) at org.example.OuterClass.call(OuterClass.groovy:12) at org.example.OuterClass.main(OuterClass.groovy:19)
This did not happen with Groovy 3.0.5.
ASM CheckClassAdapter output / Groovy 3.0.6 bytecode KO
org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 34: Method owner: expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found [Ljava/lang/Object; at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:291) at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1063) at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1021) at org.example.OuterClass.main(OuterClass.groovy:18) Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found [Ljava/lang/Object; at org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:390) at org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:43) at org.objectweb.asm.tree.analysis.Frame.executeInvokeInsn(Frame.java:646) at org.objectweb.asm.tree.analysis.Frame.execute(Frame.java:573) at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:187) ... 3 more doCall()Ljava/lang/Object; 00000 OuterClass$_call_closure1 . : : NEW org/codehaus/groovy/runtime/GStringImpl 00001 OuterClass$_call_closure1 . : GStringImpl : DUP 00002 OuterClass$_call_closure1 . : GStringImpl GStringImpl : ICONST_1 00003 OuterClass$_call_closure1 . : GStringImpl GStringImpl I : ANEWARRAY java/lang/Object 00004 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object : DUP 00005 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object : ICONST_0 00006 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I : ALOAD 0 00007 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I OuterClass$_call_closure1 : CHECKCAST org/example/OuterClass$_call_closure1 00008 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I OuterClass$_call_closure1 : INVOKEVIRTUAL org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object; 00009 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I Object : LDC Lorg/example/OuterClass;.class 00010 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I Object Class : INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object; 00011 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I Object : CHECKCAST org/example/OuterClass 00012 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I OuterClass : INVOKEVIRTUAL org/example/OuterClass.getCounter ()I Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found [Ljava/lang/Object; 00013 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I I : ICONST_1 00014 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I I I : IADD 00015 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I I : DUP 00016 OuterClass$_call_closure1 . : GStringImpl GStringImpl Object Object I I I : ISTORE 1 00017 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I : ALOAD 0 00018 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I OuterClass$_call_closure1 : INVOKEVIRTUAL groovy/lang/Closure.getThisObject ()Ljava/lang/Object; 00019 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I Object : CHECKCAST org/example/OuterClass 00020 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I OuterClass : ILOAD 1 00021 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I OuterClass I : INVOKESTATIC org/example/OuterClass.pfaccess$00 (Lorg/example/OuterClass;I)I 00022 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I I : INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; 00023 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I I Integer : AASTORE 00024 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object : ICONST_2 00025 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object I : ANEWARRAY java/lang/String 00026 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String : DUP 00027 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String : ICONST_0 00028 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String I : LDC "Hello" 00029 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String I String : AASTORE 00030 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String : DUP 00031 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String : ICONST_1 00032 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String I : LDC "Bar" 00033 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String String I String : AASTORE 00034 OuterClass$_call_closure1 I : GStringImpl GStringImpl Object Object String : INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> ([Ljava/lang/Object;[Ljava/lang/String;)V 00035 ? : ARETURN 00036 ? : L0 00037 ? : FRAME FULL [] [java/lang/Throwable] 00038 ? : NOP 00039 ? : ATHROW
ASM CheckClassAdapter output / Groovy 3.0.5 OK
doCall()Ljava/lang/Object; 00000 OuterClass$_call_closure1 : : NEW org/codehaus/groovy/runtime/GStringImpl 00001 OuterClass$_call_closure1 : GStringImpl : DUP 00002 OuterClass$_call_closure1 : GStringImpl GStringImpl : ICONST_1 00003 OuterClass$_call_closure1 : GStringImpl GStringImpl I : ANEWARRAY java/lang/Object 00004 OuterClass$_call_closure1 : GStringImpl GStringImpl Object : DUP 00005 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object : ICONST_0 00006 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I : ALOAD 0 00007 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I OuterClass$_call_closure1 : CHECKCAST org/example/OuterClass$_call_closure1 00008 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I OuterClass$_call_closure1 : INVOKEVIRTUAL org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object; 00009 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I Object : LDC Lorg/example/OuterClass;.class 00010 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I Object Class : INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object; 00011 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I Object : CHECKCAST org/example/OuterClass 00012 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I OuterClass : INVOKEVIRTUAL org/example/OuterClass.getCounter ()I 00013 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I : ICONST_1 00014 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I I : IADD 00015 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I : DUP 00016 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I I : INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; 00017 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I Integer : LDC Lorg/example/OuterClass$_call_closure1;.class 00018 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I Integer Class : ALOAD 0 00019 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I Integer Class OuterClass$_call_closure1 : LDC "counter" 00020 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I Integer Class OuterClass$_call_closure1 String : CHECKCAST java/lang/String 00021 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I Integer Class OuterClass$_call_closure1 String : INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.setGroovyObjectProperty (Ljava/lang/Object;Ljava/lang/Class;Lgroovy/lang/GroovyObject;Ljava/lang/String;)V 00022 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I I : INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; 00023 OuterClass$_call_closure1 : GStringImpl GStringImpl Object Object I Integer : AASTORE 00024 OuterClass$_call_closure1 : GStringImpl GStringImpl Object : ICONST_2 00025 OuterClass$_call_closure1 : GStringImpl GStringImpl Object I : ANEWARRAY java/lang/String 00026 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String : DUP 00027 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String : ICONST_0 00028 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String I : LDC "Hello" 00029 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String I String : AASTORE 00030 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String : DUP 00031 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String : ICONST_1 00032 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String I : LDC "Bar" 00033 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String String I String : AASTORE 00034 OuterClass$_call_closure1 : GStringImpl GStringImpl Object String : INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> ([Ljava/lang/Object;[Ljava/lang/String;)V 00035 OuterClass$_call_closure1 : GStringImpl : ARETURN 00036 ? : L0 00037 ? : FRAME FULL [] [java/lang/Throwable] 00038 ? : NOP 00039 ? : ATHROW
Workaround
A workaround is to lift the unary operation out of the GString (i.e. use a temporary variable).
Attachments
Issue Links
- relates to
-
GROOVY-7304 Cannot mutate private field from within an AIC or a closure
- Closed