You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Andreas Turban (JIRA)" <ji...@apache.org> on 2019/04/16 06:46:00 UTC

[jira] [Created] (GROOVY-9086) @CompileStatic of closure calls with OWNER_FIRST fail at runtime with ClassCastException

Andreas Turban created GROOVY-9086:
--------------------------------------

             Summary: @CompileStatic of closure calls with OWNER_FIRST fail at runtime with ClassCastException
                 Key: GROOVY-9086
                 URL: https://issues.apache.org/jira/browse/GROOVY-9086
             Project: Groovy
          Issue Type: Bug
          Components: Static compilation
    Affects Versions: 2.5.6
         Environment: WIndows7, Groovy 2.5.6, Java 8 + 11
            Reporter: Andreas Turban
         Attachments: TestScript.groovy

The attached script fails with a ClassCastException, when method m2 is annotated with 

 
{code:java}
strategy = Closure.OWNER_FIRST
{code}
 

but work with 

 
{code:java}
strategy = Closure.DELEGATE_FIRST
{code}
 

The expected system-out should be 

 
{code:java}
c1Method called{code}
 

in both cases. The generated bytecode for closure Test$_test_closure1$_closure2.class contains a call to getDelegate() instead of getOwner() in case of Closure.OWNER_FIRST. But correctly generates code getOwner() in case of Closure.DELEGATE_FIRST.

The resulting ClassCastException at runtime is:
{code:java}
java.lang.ClassCastException: Test$C3 cannot be cast to groovy.lang.Closure
at Test$_test_closure1$_closure2$_closure3.doCall(TestScript.groovy:28)
at Test$_test_closure1$_closure2$_closure3.doCall(TestScript.groovy)
at Test.m3(TestScript.groovy:20)
at Test$_test_closure1$_closure2.doCall(TestScript.groovy:27)
at Test$_test_closure1$_closure2.doCall(TestScript.groovy)
at Test.m2(TestScript.groovy:14)
at Test$_test_closure1.doCall(TestScript.groovy:26)
at Test$_test_closure1.doCall(TestScript.groovy)
at Test.m1(TestScript.groovy:8)
at Test.test(TestScript.groovy:25)
at Test$test.call(Unknown Source)
at TestScript.run(TestScript.groovy:45)
{code}
 

 

The wrong bytecode for case Closure.OWNER_FIRST:
{code:java}
public java.lang.Object doCall(java.lang.Object);
descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_0
1: checkcast #2 // class Test$_test_closure1$_closure2
4: invokevirtual #29 // Method getDelegate:()Ljava/lang/Object;
7: checkcast #4 // class groovy/lang/Closure
10: invokevirtual #30 // Method groovy/lang/Closure.getDelegate:()Ljava/lang/Object;
13: checkcast #32 // class Test$C1
16: invokevirtual #36 // Method Test$C1.c1Method:()V
19: aconst_null
20: areturn
{code}
The correct bytecode for case Closure.DELEGATE_FIRST:
{code:java}
public java.lang.Object doCall(java.lang.Object);
descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_0
1: checkcast #2 // class Test$_test_closure1$_closure2
4: invokevirtual #29 // Method getOwner:()Ljava/lang/Object;
7: checkcast #4 // class groovy/lang/Closure
10: invokevirtual #32 // Method groovy/lang/Closure.getDelegate:()Ljava/lang/Object;
13: checkcast #34 // class Test$C1
16: invokevirtual #38 // Method Test$C1.c1Method:()V
19: aconst_null
20: areturn
{code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)