You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/02/25 02:04:14 UTC
[groovy] 02/02: GROOVY-9211: BUG! UNCAUGHT EXCEPTION on
OpenJDK14-ea+8 (adjust for better JDK8 lookup)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 78430bae4ece202d764a18547669a6f9bf740a24
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Feb 24 10:09:14 2020 +1000
GROOVY-9211: BUG! UNCAUGHT EXCEPTION on OpenJDK14-ea+8 (adjust for better JDK8 lookup)
---
.../org/codehaus/groovy/vmplugin/v8/Java8.java | 72 ++++++++++++++++++++++
.../groovy/runtime/InterfaceConversionTest.groovy | 2 -
2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
index f4bd201..3c1bc32 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
@@ -18,12 +18,17 @@
*/
package org.codehaus.groovy.vmplugin.v8;
+import groovy.lang.GroovyRuntimeException;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.CompileUnit;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.vmplugin.v7.Java7;
import java.lang.annotation.ElementType;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -83,4 +88,71 @@ public class Java8 extends Java7 {
}
return params;
}
+
+ private static class LookupHolder {
+ private static final Method PRIVATE_LOOKUP;
+ private static final Constructor<MethodHandles.Lookup> LOOKUP_Constructor;
+
+ static {
+ Constructor<MethodHandles.Lookup> lookup = null;
+ Method privateLookup = null;
+ try { // java 9+ friendly
+ privateLookup = MethodHandles.class.getMethod("privateLookupIn", Class.class, MethodHandles.Lookup.class);
+ } catch (final NoSuchMethodException | RuntimeException e) { // java 8 or fallback if anything else goes wrong
+ try {
+ lookup = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);
+ if (!lookup.isAccessible()) {
+ trySetAccessible(lookup);
+ }
+ } catch (final NoSuchMethodException ex) {
+ throw new IllegalStateException("Incompatible JVM", e);
+ }
+ }
+ PRIVATE_LOOKUP = privateLookup;
+ LOOKUP_Constructor = lookup;
+ }
+ }
+
+ private static boolean trySetAccessible(AccessibleObject ao) {
+ try {
+ ao.setAccessible(true);
+ return true;
+ } catch (SecurityException e) {
+ throw e;
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+
+ private static Constructor<MethodHandles.Lookup> getLookupConstructor() {
+ return LookupHolder.LOOKUP_Constructor;
+ }
+
+ private static Method getPrivateLookup() {
+ return LookupHolder.PRIVATE_LOOKUP;
+ }
+
+ public static MethodHandles.Lookup of(final Class<?> declaringClass) {
+ try {
+ final Method privateLookup = getPrivateLookup();
+ if (privateLookup != null) {
+ return (MethodHandles.Lookup) privateLookup.invoke(null, declaringClass, MethodHandles.lookup());
+ }
+ return getLookupConstructor().newInstance(declaringClass, MethodHandles.Lookup.PRIVATE).in(declaringClass);
+ } catch (final IllegalAccessException | InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ } catch (final InvocationTargetException e) {
+ throw new GroovyRuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object getInvokeSpecialHandle(Method method, Object receiver) {
+ final Class<?> receiverType = receiver.getClass();
+ try {
+ return of(receiverType).unreflectSpecial(method, receiverType).bindTo(receiver);
+ } catch (ReflectiveOperationException e) {
+ return super.getInvokeSpecialHandle(method, receiver);
+ }
+ }
}
diff --git a/src/test/org/codehaus/groovy/runtime/InterfaceConversionTest.groovy b/src/test/org/codehaus/groovy/runtime/InterfaceConversionTest.groovy
index be6a385..30bcc93 100644
--- a/src/test/org/codehaus/groovy/runtime/InterfaceConversionTest.groovy
+++ b/src/test/org/codehaus/groovy/runtime/InterfaceConversionTest.groovy
@@ -45,8 +45,6 @@ class InterfaceConversionTest extends GroovyTestCase {
void testDefaultInterfaceMethodCallOnProxy() {
// reversed is a default method within the Comparator interface for 1.8+
if (!isAtLeastJdk("1.8")) return
- // broken on JDK14, TODO: FIX
- if (isAtLeastJdk("14.0")) return
Comparator c1 = { a, b -> a <=> b }
assert c1.compare("a", "b") == -1
def c2 = c1.reversed()