-
Bug
-
Resolution: Unresolved
-
Minor
-
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.
- is blocked by
-
JENKINS-68690 Upgrade Groovy from 3.0.x to 4.0.x
-
- Open
-
[JENKINS-73031] Groovy 2.x regresses to Java 6 bytecode when running JDK 14+
Link | New: This issue is blocked by JENKINS-68690 [ JENKINS-68690 ] |
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. |
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. |