[ 
https://issues.apache.org/jira/browse/GROOVY-7526?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14647367#comment-14647367
 ] 

Jochen Theodorou commented on GROOVY-7526:
------------------------------------------

seems like the bytecode comes directly from StaticCallSiteWriter#makeGetField. 
So no type propagation problem
Looking at the bytecode in more detail, the part of interest is actually {code}
    ALOAD 1                                                                     
              // load jdata on stack
    DUP                                                                         
                 // have 2 jdata on stack
    IFNONNULL L3                                                                
        // if top jdata==null goto L3 else goto L4. stack=jdata 
    GOTO L4
   L3
    GETFIELD JavaTool$Data.fieldData : Ljava/lang/String;         // get field 
value, stack=String
   L4
    INVOKEDYNAMIC cast(Ljava/lang/String;)Z [...]                     
{code}
so following the L3 branch we get to L4 with a String on the stack. Jumping 
directly to L4 we will have a jdata there instead.  We know that this jdata is 
null, but the type information the verifier has is not interested in that. 
Doing either a CHECKCAST, or simply poping the value and loading null, before 
GOTO L4 should solve the problem

> Safe navigation broken on java fields with indy and @CompileStatic
> ------------------------------------------------------------------
>
>                 Key: GROOVY-7526
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7526
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation
>    Affects Versions: 2.4.3
>            Reporter: Matthew Turnbull
>            Priority: Minor
>         Attachments: groovy_test.tar.gz
>
>
> Trying to directly access a native Java object field, from a Groovy class 
> compiled with invokedynamic and @CompileStatic, causes a 
> "java.lang.VerifyError: Bad type on operand stack" error.
> I have reproduced this on Linux with Groovy 2.4.3/2.4.4 and Java 1.7.0_80 
> (64bit).
> {noformat}
> ~ $ cd /tmp/groovy_test/
> /tmp/groovy_test $ rm -f com/*.class
> /tmp/groovy_test $ javac com/*.java
> /tmp/groovy_test $ /opt/groovy-2.4.4/bin/groovyc --indy --configscript 
> config.groovyc com/*.groovy
> /tmp/groovy_test $ java -cp .:/opt/groovy-2.4.4/lib/groovy-2.4.4.jar com.Test
> {noformat}
> {noformat}
> Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
> Exception Details:
>   Location:
>     com/Controller.run()V @55: invokedynamic
>   Reason:
>     Type 'java/lang/Object' (current frame, stack[0]) is not assignable to 
> 'java/lang/String'
>   Current Frame:
>     bci: @55
>     flags: { }
>     locals: { 'com/Controller', 'com/GroovyTool$Data', 'com/GroovyTool$Data', 
> 'com/JavaTool$Data' }
>     stack: { 'java/lang/Object' }
>   Bytecode:
>     0000000: b800 224c 2b57 2b59 4dc6 000a 2cb6 0028
>     0000010: a700 0401 ba00 3600 0099 000d b200 3c12
>     0000020: 3eb6 0044 0157 b800 494e 2d57 2d59 c700
>     0000030: 06a7 0006 b400 4fba 0036 0000 9900 0db2
>     0000040: 003c 1251 b600 4401 57b1               
>   Stackmap Table:
>     append_frame(@19,Object[#36],Object[#36])
>     same_locals_1_stack_item_frame(@20,Object[#87])
>     same_frame(@38)
>     
> full_frame(@52,{Object[#2],Object[#36],Object[#36],Object[#75]},{Object[#75]})
>     same_locals_1_stack_item_frame(@55,Object[#4])
>     same_frame(@73)
>       at java.lang.Class.getDeclaredConstructors0(Native Method)
>       at java.lang.Class.privateGetDeclaredConstructors(Class.java:2595)
>       at java.lang.Class.getConstructor0(Class.java:2895)
>       at java.lang.Class.newInstance(Class.java:354)
>       at com.Test.loadController(Test.java:20)
>       at com.Test.test(Test.java:30)
>       at com.Test.main(Test.java:10)
> {noformat}
> Work arounds that I found:
> * Remove @CompileStatic
> * Disable --indy
> * Cast the safely navigated field to it's object type i.e. (String)data?.field
> * Define a getter method to use in lieu of the field.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to