[jira] [Updated] (GROOVY-8579) No bytecode level check is done before producing JDK8+ bytecodes

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[jira] [Updated] (GROOVY-8579) No bytecode level check is done before producing JDK8+ bytecodes

JIRA jira@apache.org

     [ https://issues.apache.org/jira/browse/GROOVY-8579?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Paul King updated GROOVY-8579:
------------------------------
    Description:
Create a file using a JDK8 static interface method, e.g. {{MyScript.groovy}}:
{code:java}
import groovy.transform.CompileStatic

@CompileStatic
Comparator myMethod() {
    Map.Entry.comparingByKey()
}
{code}
Compile using JDK8. On Groovy 3.0, use {{-Dgroovy.target.bytecode=1.7}} (not required for 2.5/6).

Note from {{javap -v}} that the bytecode version is:
{noformat}
 major version: 51
{noformat}
and that an InterfaceMethodref to the {{Map.Entry}} static interface method exists:
{noformat}
   #48 = InterfaceMethodref #45.#47       // java/util/Map$Entry.comparingByKey:()Ljava/util/Comparator;
{noformat}
Now try to use that class in another script, e.g.:
{code:java}
println new MyScript().myMethod()
{code}
You will note this error:
{noformat}
java.lang.VerifyError: Illegal type at constant pool entry 48 in class MyScript
Exception Details:
  Location:
    MyScript.myMethod()Ljava/util/Comparator; @0: invokestatic
  Reason:
    Constant pool index 48 is invalid
{noformat}
For Groovy 2.5/6 you can just run {{groovy MyScript.groovy}} to see the VerifyError, though using groovyc will let you see the generated bytecode.

So there are two problems:
* we should not set bytecode level to be the minimum level for the Groovy version (7 is default for 2.5/6) when producing bytecode requiring JDK8+.
* we should probably just complain if {{groovy.target.bytecode}} is ever set below the minimum value for the particular Groovy version.

  was:
Create a file using a JDK8 static interface method, e.g. {{MyScript.groovy}}:
{code:java}
import groovy.transform.CompileStatic

@CompileStatic
Comparator myMethod() {
    Map.Entry.comparingByKey()
}
{code}
Compile using JDK8 but with {{-Dgroovy.target.bytecode=1.7}}.

Note from {{javap -v}} that the bytecode version is:
{noformat}
 major version: 51
{noformat}
and that an InterfaceMethodref to the {{Map.Entry}} static interface method exists:
{noformat}
   #48 = InterfaceMethodref #45.#47       // java/util/Map$Entry.comparingByKey:()Ljava/util/Comparator;
{noformat}
Now try to use that class in another script, e.g.:
{code:java}
println new MyScript().myMethod()
{code}
You will note this error:
{noformat}
java.lang.VerifyError: Illegal type at constant pool entry 48 in class MyScript
Exception Details:
  Location:
    MyScript.myMethod()Ljava/util/Comparator; @0: invokestatic
  Reason:
    Constant pool index 48 is invalid
{noformat}


> No bytecode level check is done before producing JDK8+ bytecodes
> ----------------------------------------------------------------
>
>                 Key: GROOVY-8579
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8579
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Paul King
>            Priority: Major
>
> Create a file using a JDK8 static interface method, e.g. {{MyScript.groovy}}:
> {code:java}
> import groovy.transform.CompileStatic
> @CompileStatic
> Comparator myMethod() {
>     Map.Entry.comparingByKey()
> }
> {code}
> Compile using JDK8. On Groovy 3.0, use {{-Dgroovy.target.bytecode=1.7}} (not required for 2.5/6).
> Note from {{javap -v}} that the bytecode version is:
> {noformat}
>  major version: 51
> {noformat}
> and that an InterfaceMethodref to the {{Map.Entry}} static interface method exists:
> {noformat}
>    #48 = InterfaceMethodref #45.#47       // java/util/Map$Entry.comparingByKey:()Ljava/util/Comparator;
> {noformat}
> Now try to use that class in another script, e.g.:
> {code:java}
> println new MyScript().myMethod()
> {code}
> You will note this error:
> {noformat}
> java.lang.VerifyError: Illegal type at constant pool entry 48 in class MyScript
> Exception Details:
>   Location:
>     MyScript.myMethod()Ljava/util/Comparator; @0: invokestatic
>   Reason:
>     Constant pool index 48 is invalid
> {noformat}
> For Groovy 2.5/6 you can just run {{groovy MyScript.groovy}} to see the VerifyError, though using groovyc will let you see the generated bytecode.
> So there are two problems:
> * we should not set bytecode level to be the minimum level for the Groovy version (7 is default for 2.5/6) when producing bytecode requiring JDK8+.
> * we should probably just complain if {{groovy.target.bytecode}} is ever set below the minimum value for the particular Groovy version.



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