From notifications-return-15999-archive-asf-public=cust-asf.ponee.io@groovy.apache.org Wed Apr 3 04:29:05 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id EA976180668 for ; Wed, 3 Apr 2019 06:29:04 +0200 (CEST) Received: (qmail 10845 invoked by uid 500); 3 Apr 2019 04:29:03 -0000 Mailing-List: contact notifications-help@groovy.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.apache.org Delivered-To: mailing list notifications@groovy.apache.org Received: (qmail 10836 invoked by uid 99); 3 Apr 2019 04:29:03 -0000 Received: from mailrelay1-us-west.apache.org (HELO mailrelay1-us-west.apache.org) (209.188.14.139) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 03 Apr 2019 04:29:03 +0000 Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 3863AE00CC for ; Wed, 3 Apr 2019 04:29:03 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id D59DE24597 for ; Wed, 3 Apr 2019 04:29:02 +0000 (UTC) Date: Wed, 3 Apr 2019 04:29:02 +0000 (UTC) From: =?utf-8?Q?Fr=C3=A9d=C3=A9ric_Chuong_=28JIRA=29?= To: notifications@groovy.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Created] (GROOVY-9063) @CompileStatic generates invalid bytecode (leading to runtime ClassCastException) when accessing protected instance member from 2 level of nested closures MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 Fr=C3=A9d=C3=A9ric Chuong created GROOVY-9063: --------------------------------------- Summary: @CompileStatic generates invalid bytecode (leading to= runtime ClassCastException) when accessing protected instance member from = 2 level of nested closures Key: GROOVY-9063 URL: https://issues.apache.org/jira/browse/GROOVY-9063 Project: Groovy Issue Type: Bug Components: Static compilation Reporter: Fr=C3=A9d=C3=A9ric Chuong Provided the following class: {code:groovy} import groovy.transform.CompileStatic import org.objectweb.asm.ClassReader import org.objectweb.asm.util.TraceClassVisitor @CompileStatic class NoBug { protected String message =3D "hello" void noBug() { { -> { -> printClass(getClass().name) message.length() }.call() }.call() } static void printClass(String className) { new ClassReader(className).accept(new TraceClassVisitor(new PrintWr= iter(System.out)), 0) } static void main(String[] args) { new NoBug().noBug() } } {code} {panel:title=3DNo problem with 2.5.5|borderColor=3Dgreen} Compilation ans execution with Groovy 2.5.5 works fine and produce the foll= owing output: {noformat} // class version 52.0 (52) // access flags 0x31 public final class groovy255/NoBug$_noBug_closure1$_closure2 extends groovy= /lang/Closure implements org/codehaus/groovy/runtime/GeneratedClosure { // compiled from: NoBug.groovy OUTERCLASS groovy255/NoBug$_noBug_closure1 doCall ()Ljava/lang/Object; // access flags 0x11 public final INNERCLASS groovy255/NoBug$_noBug_closure1$_closure2 null _c= losure2 // access flags 0x100A private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $stat= icClassInfo // access flags 0x1089 public static transient synthetic Z __$stMC // access flags 0x1 public (Ljava/lang/Object;Ljava/lang/Object;)V L0 ALOAD 0 ALOAD 1 ALOAD 2 INVOKESPECIAL groovy/lang/Closure. (Ljava/lang/Object;Ljava/lang/= Object;)V L1 RETURN LOCALVARIABLE this Lgroovy255/NoBug$_noBug_closure1$_closure2; L0 L1 0 LOCALVARIABLE _outerInstance Ljava/lang/Object; L0 L1 1 LOCALVARIABLE _thisObject Ljava/lang/Object; L0 L1 2 MAXSTACK =3D 3 MAXLOCALS =3D 3 // access flags 0x1 public doCall()Ljava/lang/Object; L0 LINENUMBER 14 L0 ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String; INVOKESTATIC groovy255/NoBug.printClass (Ljava/lang/String;)V ACONST_NULL POP L1 LINENUMBER 15 L1 ALOAD 0 LDC "message" INVOKEINTERFACE groovy/lang/GroovyObject.getProperty (Ljava/lang/String= ;)Ljava/lang/Object; (itf) CHECKCAST java/lang/String INVOKEVIRTUAL java/lang/String.length ()I INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; ARETURN L2 LINENUMBER 14 L2 FRAME FULL [] [java/lang/Throwable] NOP ATHROW LOCALVARIABLE this Lgroovy255/NoBug$_noBug_closure1$_closure2; L0 L2 0 MAXSTACK =3D 2 MAXLOCALS =3D 1 // access flags 0x1004 protected synthetic $getStaticMetaClass()Lgroovy/lang/MetaClass; ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; LDC Lgroovy255/NoBug$_noBug_closure1$_closure2;.class IF_ACMPEQ L0 ALOAD 0 INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.initMeta= Class (Ljava/lang/Object;)Lgroovy/lang/MetaClass; ARETURN L0 FRAME SAME GETSTATIC groovy255/NoBug$_noBug_closure1$_closure2.$staticClassInfo : = Lorg/codehaus/groovy/reflection/ClassInfo; ASTORE 1 ALOAD 1 IFNONNULL L1 ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; INVOKESTATIC org/codehaus/groovy/reflection/ClassInfo.getClassInfo (Lja= va/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo; DUP ASTORE 1 PUTSTATIC groovy255/NoBug$_noBug_closure1$_closure2.$staticClassInfo : = Lorg/codehaus/groovy/reflection/ClassInfo; L1 FRAME APPEND [org/codehaus/groovy/reflection/ClassInfo] ALOAD 1 INVOKEVIRTUAL org/codehaus/groovy/reflection/ClassInfo.getMetaClass ()L= groovy/lang/MetaClass; ARETURN MAXSTACK =3D 2 MAXLOCALS =3D 2 } {noformat} {panel} {panel:title=3DProblem with 2.5.6|borderColor=3Dred} Now with Groovy 2.5.6, compilation seems fine but execution leads to {{Clas= sCastException}}, and inspection of the inner closure reveals that the byte= code differs: {noformat} // class version 52.0 (52) // access flags 0x31 public final class groovy256/Bug$_bug_closure1$_closure2 extends groovy/lan= g/Closure implements org/codehaus/groovy/runtime/GeneratedClosure { // compiled from: Bug.groovy OUTERCLASS groovy256/Bug$_bug_closure1 doCall ()Ljava/lang/Object; // access flags 0x11 public final INNERCLASS groovy256/Bug$_bug_closure1$_closure2 null _closu= re2 // access flags 0x100A private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $stat= icClassInfo // access flags 0x1089 public static transient synthetic Z __$stMC // access flags 0x1 public (Ljava/lang/Object;Ljava/lang/Object;)V L0 ALOAD 0 ALOAD 1 ALOAD 2 INVOKESPECIAL groovy/lang/Closure. (Ljava/lang/Object;Ljava/lang/= Object;)V L1 RETURN LOCALVARIABLE this Lgroovy256/Bug$_bug_closure1$_closure2; L0 L1 0 LOCALVARIABLE _outerInstance Ljava/lang/Object; L0 L1 1 LOCALVARIABLE _thisObject Ljava/lang/Object; L0 L1 2 MAXSTACK =3D 3 MAXLOCALS =3D 3 // access flags 0x1 public doCall()Ljava/lang/Object; L0 LINENUMBER 14 L0 ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String; INVOKESTATIC groovy256/Bug.printClass (Ljava/lang/String;)V ACONST_NULL POP L1 LINENUMBER 15 L1 ALOAD 0 CHECKCAST groovy256/Bug$_bug_closure1$_closure2 INVOKEVIRTUAL groovy256/Bug$_bug_closure1$_closure2.getOwner ()Ljava/la= ng/Object; CHECKCAST groovy256/Bug GETFIELD groovy256/Bug.message : Ljava/lang/String; INVOKEVIRTUAL java/lang/String.length ()I INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; ARETURN L2 LINENUMBER 14 L2 FRAME FULL [] [java/lang/Throwable] NOP ATHROW LOCALVARIABLE this Lgroovy256/Bug$_bug_closure1$_closure2; L0 L2 0 MAXSTACK =3D 1 MAXLOCALS =3D 1 // access flags 0x1004 protected synthetic $getStaticMetaClass()Lgroovy/lang/MetaClass; ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; LDC Lgroovy256/Bug$_bug_closure1$_closure2;.class IF_ACMPEQ L0 ALOAD 0 INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.initMeta= Class (Ljava/lang/Object;)Lgroovy/lang/MetaClass; ARETURN L0 FRAME SAME GETSTATIC groovy256/Bug$_bug_closure1$_closure2.$staticClassInfo : Lorg= /codehaus/groovy/reflection/ClassInfo; ASTORE 1 ALOAD 1 IFNONNULL L1 ALOAD 0 INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; INVOKESTATIC org/codehaus/groovy/reflection/ClassInfo.getClassInfo (Lja= va/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo; DUP ASTORE 1 PUTSTATIC groovy256/Bug$_bug_closure1$_closure2.$staticClassInfo : Lorg= /codehaus/groovy/reflection/ClassInfo; L1 FRAME APPEND [org/codehaus/groovy/reflection/ClassInfo] ALOAD 1 INVOKEVIRTUAL org/codehaus/groovy/reflection/ClassInfo.getMetaClass ()L= groovy/lang/MetaClass; ARETURN MAXSTACK =3D 2 MAXLOCALS =3D 2 } {noformat} {noformat} groovy256.Bug$_bug_closure1 cannot be cast to groovy256.Bug java.lang.ClassCastException: groovy256.Bug$_bug_closure1 cannot be cast to= groovy256.Bug =09at groovy256.Bug$_bug_closure1$_closure2.doCall(Bug.groovy:15) =09at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) =09at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.= java:62) =09at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces= sorImpl.java:43) =09at java.lang.reflect.Method.invoke(Method.java:498) =09at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:= 101) =09at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323) =09at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(C= losureMetaClass.java:263) =09at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041) =09at groovy.lang.Closure.call(Closure.java:405) =09at groovy.lang.Closure.call(Closure.java:399) =09at groovy256.Bug$_bug_closure1.doCall(Bug.groovy:13) =09at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) =09at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.= java:62) =09at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces= sorImpl.java:43) =09at java.lang.reflect.Method.invoke(Method.java:498) =09at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:= 101) =09at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323) =09at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(C= losureMetaClass.java:263) =09at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041) =09at groovy.lang.Closure.call(Closure.java:405) =09at groovy.lang.Closure.call(Closure.java:399) =09at groovy256.Bug.bug(Bug.groovy:12) =09at groovy256.BugTest.bug(BugTest.java:11) =09at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) =09at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.= java:62) =09at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces= sorImpl.java:43) =09at java.lang.reflect.Method.invoke(Method.java:498) =09at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(Framework= Method.java:50) =09at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCal= lable.java:12) =09at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMe= thod.java:47) =09at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMet= hod.java:17) =09at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) =09at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRun= ner.java:78) =09at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRun= ner.java:57) =09at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) =09at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) =09at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) =09at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) =09at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) =09at org.junit.runners.ParentRunner.run(ParentRunner.java:363) =09at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.ru= nTestClass(JUnitTestClassExecutor.java:110) =09at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.ex= ecute(JUnitTestClassExecutor.java:58) =09at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.ex= ecute(JUnitTestClassExecutor.java:38) =09at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassPro= cessor.processTestClass(AbstractJUnitTestClassProcessor.java:62) =09at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.process= TestClass(SuiteTestClassProcessor.java:51) =09at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) =09at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.= java:62) =09at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces= sorImpl.java:43) =09at java.lang.reflect.Method.invoke(Method.java:498) =09at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDi= spatch.java:35) =09at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDi= spatch.java:24) =09at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(Cont= extClassLoaderDispatch.java:32) =09at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocati= onHandler.invoke(ProxyDispatchAdapter.java:93) =09at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) =09at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestCl= ass(TestWorker.java:118) =09at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) =09at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.= java:62) =09at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces= sorImpl.java:43) =09at java.lang.reflect.Method.invoke(Method.java:498) =09at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDi= spatch.java:35) =09at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDi= spatch.java:24) =09at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnect= ion$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175) =09at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnect= ion$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157) =09at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(Messag= eHub.java:404) =09at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.= onExecute(ExecutorPolicy.java:63) =09at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecu= torImpl.java:46) =09at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.= java:1149) =09at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor= .java:624) =09at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnabl= e.run(ThreadFactoryImpl.java:55) =09at java.lang.Thread.run(Thread.java:748) {noformat} {panel} {panel:title=3DNote} Replacing {noformat} message.length() {noformat} with {noformat} this.@message.length() {noformat} does not exhibit that problem. {panel} This may be related to [GROOVY-7687] which relates to similar conditions (n= ested closure and {{\@CompileStatic}} -- This message was sent by Atlassian JIRA (v7.6.3#76005)