Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-73031

Groovy 2.x regresses to Java 6 bytecode when running JDK 14+

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • core
    • None

      When running on JDK 14 or newer, Groovy 2.x regresses to using Java 6 bytecode for generated classes rather than Java 8 bytecode as it does when running on JDK 11 to JDK 13. This breaks some language features, in particular static interface methods like List.of. Attempting to call such a method in a Groovy script will throw a VerifyError like the following:

      java.lang.VerifyError: (class: java_util_List$of$17, method: call signature: (Ljava/lang/Object;)Ljava/lang/Object;) Illegal type in constant pool
      

      The reason for the change in behavior is that https://github.com/openjdk/jdk/commit/068575e9b11703d67af45bac0944b0d521f69fba, which appears to have first landed in JDK 14, modified the signature of the (private) constructor that Groovy uses to check for JDK 7+ support (see here). Since the JDK 8 support class extends the JDK 7 support class, the JDK 8 support class also fails to load on JDK 14+ (see Java8).

      This causes Groovy’s VMPluginFactory.getPlugin to return the Java6 plugin on Java 14+ (see here), which in turn means that classes generated by Groovy use Java 6 bytecode, and that breaks some Java 8 language features like calls to static interface methods.

      With JDK 7-13, the signature of the private MethodHandles.Lookup constructor matches what Groovy expects, so Groovy uses Java 8 bytecode.

      I think that the earliest fix for this in Groovy is this commit which landed in Groovy 4.x, but perhaps there is an earlier fix as well.

      I am not aware of any workaround other than avoiding direct calls to static interface methods from Groovy scripts.

          [JENKINS-73031] Groovy 2.x regresses to Java 6 bytecode when running JDK 14+

          Devin Nusbaum created issue -
          Devin Nusbaum made changes -
          Link New: This issue is blocked by JENKINS-68690 [ JENKINS-68690 ]
          Devin Nusbaum made changes -
          Description Original: When running on JDK 14 or newer, Groovy 2.x regresses to using Java 6 bytecode for generated classes rather than Java 8 bytecode as it does when running on JDK 11 to JDK 13. This breaks some language features, in particular static interface methods like {{{}List.of{}}}. Attempting to call such a method in a Groovy script will throw a {{VerifyError}} like the following:
          {noformat}
          java.lang.VerifyError: (class: java_util_List$of$17, method: call signature: (Ljava/lang/Object;)Ljava/lang/Object;) Illegal type in constant pool
          {noformat}
          The reason for the change in behavior is that [https://github.com/openjdk/jdk/commit/068575e9b11703d67af45bac0944b0d521f69fba], which appears to have first landed in JDK 14, modified the signature of the (private) constructor that Groovy uses to check for JDK 7+ support (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v7/Java7.java#L43]). Since the JDK 8 support class extends the JDK 7 support class, the JDK 8 support class also fails to load on JDK 14+ (see [Java8|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v8/Java8.java#L32]).

          This causes Groovy’s `VMPluginFactory.getPlugin` to return the `Java6` plugin on Java 14+ (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/VMPluginFactory.java#L41-L54]), which in turn means that classes generated by Groovy use Java 6 bytecode, and that breaks some Java 8 language features like calls to static interface methods.

          With JDK 7-13, the signature of the private `MethodHandles.Lookup` constructor matches what Groovy expects, so Groovy uses Java 8 bytecode.

          I think that the earliest fix for this in Groovy is [this commit|https://github.com/apache/groovy/pull/1153] which landed in Groovy 4.x, but perhaps there is an earlier fix as well.

          I am not aware of any workaround, other than avoiding direct calls to static interface methods from Groovy scripts.
          New: When running on JDK 14 or newer, Groovy 2.x regresses to using Java 6 bytecode for generated classes rather than Java 8 bytecode as it does when running on JDK 11 to JDK 13. This breaks some language features, in particular static interface methods like {{{}List.of{}}}. Attempting to call such a method in a Groovy script will throw a {{VerifyError}} like the following:
          {noformat}
          java.lang.VerifyError: (class: java_util_List$of$17, method: call signature: (Ljava/lang/Object;)Ljava/lang/Object;) Illegal type in constant pool
          {noformat}
          The reason for the change in behavior is that [https://github.com/openjdk/jdk/commit/068575e9b11703d67af45bac0944b0d521f69fba], which appears to have first landed in JDK 14, modified the signature of the (private) constructor that Groovy uses to check for JDK 7+ support (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v7/Java7.java#L43]). Since the JDK 8 support class extends the JDK 7 support class, the JDK 8 support class also fails to load on JDK 14+ (see [Java8|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v8/Java8.java#L32]).

          This causes Groovy’s `VMPluginFactory.getPlugin` to return the `Java6` plugin on Java 14+ (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/VMPluginFactory.java#L41-L54]), which in turn means that classes generated by Groovy use Java 6 bytecode, and that breaks some Java 8 language features like calls to static interface methods.

          With JDK 7-13, the signature of the private `MethodHandles.Lookup` constructor matches what Groovy expects, so Groovy uses Java 8 bytecode.

          I think that the earliest fix for this in Groovy is [this commit|https://github.com/apache/groovy/pull/1153] which landed in Groovy 4.x, but perhaps there is an earlier fix as well.

          I am not aware of any workaround other than avoiding direct calls to static interface methods from Groovy scripts.
          Devin Nusbaum made changes -
          Description Original: When running on JDK 14 or newer, Groovy 2.x regresses to using Java 6 bytecode for generated classes rather than Java 8 bytecode as it does when running on JDK 11 to JDK 13. This breaks some language features, in particular static interface methods like {{{}List.of{}}}. Attempting to call such a method in a Groovy script will throw a {{VerifyError}} like the following:
          {noformat}
          java.lang.VerifyError: (class: java_util_List$of$17, method: call signature: (Ljava/lang/Object;)Ljava/lang/Object;) Illegal type in constant pool
          {noformat}
          The reason for the change in behavior is that [https://github.com/openjdk/jdk/commit/068575e9b11703d67af45bac0944b0d521f69fba], which appears to have first landed in JDK 14, modified the signature of the (private) constructor that Groovy uses to check for JDK 7+ support (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v7/Java7.java#L43]). Since the JDK 8 support class extends the JDK 7 support class, the JDK 8 support class also fails to load on JDK 14+ (see [Java8|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v8/Java8.java#L32]).

          This causes Groovy’s `VMPluginFactory.getPlugin` to return the `Java6` plugin on Java 14+ (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/VMPluginFactory.java#L41-L54]), which in turn means that classes generated by Groovy use Java 6 bytecode, and that breaks some Java 8 language features like calls to static interface methods.

          With JDK 7-13, the signature of the private `MethodHandles.Lookup` constructor matches what Groovy expects, so Groovy uses Java 8 bytecode.

          I think that the earliest fix for this in Groovy is [this commit|https://github.com/apache/groovy/pull/1153] which landed in Groovy 4.x, but perhaps there is an earlier fix as well.

          I am not aware of any workaround other than avoiding direct calls to static interface methods from Groovy scripts.
          New: When running on JDK 14 or newer, Groovy 2.x regresses to using Java 6 bytecode for generated classes rather than Java 8 bytecode as it does when running on JDK 11 to JDK 13. This breaks some language features, in particular static interface methods like {{{}List.of{}}}. Attempting to call such a method in a Groovy script will throw a {{VerifyError}} like the following:
          {noformat}
          java.lang.VerifyError: (class: java_util_List$of$17, method: call signature: (Ljava/lang/Object;)Ljava/lang/Object;) Illegal type in constant pool
          {noformat}
          The reason for the change in behavior is that [https://github.com/openjdk/jdk/commit/068575e9b11703d67af45bac0944b0d521f69fba], which appears to have first landed in JDK 14, modified the signature of the (private) constructor that Groovy uses to check for JDK 7+ support (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v7/Java7.java#L43]). Since the JDK 8 support class extends the JDK 7 support class, the JDK 8 support class also fails to load on JDK 14+ (see [Java8|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/v8/Java8.java#L32]).

          This causes Groovy’s {{VMPluginFactory.getPlugin}} to return the {{Java6}} plugin on Java 14+ (see [here|https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/org/codehaus/groovy/vmplugin/VMPluginFactory.java#L41-L54]), which in turn means that classes generated by Groovy use Java 6 bytecode, and that breaks some Java 8 language features like calls to static interface methods.

          With JDK 7-13, the signature of the private {{MethodHandles.Lookup}} constructor matches what Groovy expects, so Groovy uses Java 8 bytecode.

          I think that the earliest fix for this in Groovy is [this commit|https://github.com/apache/groovy/pull/1153] which landed in Groovy 4.x, but perhaps there is an earlier fix as well.

          I am not aware of any workaround other than avoiding direct calls to static interface methods from Groovy scripts.

            Unassigned Unassigned
            dnusbaum Devin Nusbaum
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: