You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/06/14 07:08:12 UTC

[groovy] branch danielsun/tweak-build updated: GROOVY-10138: [JDK16] Failed to invoke default method of proxy

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch danielsun/tweak-build
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/danielsun/tweak-build by this push:
     new 2c5c26b  GROOVY-10138: [JDK16] Failed to invoke default method of proxy
2c5c26b is described below

commit 2c5c26b3075d2f17d44c8109605db7acb019963c
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Jun 14 15:07:31 2021 +0800

    GROOVY-10138: [JDK16] Failed to invoke default method of proxy
---
 .../org/codehaus/groovy/vmplugin/v16/Java16.java   | 26 ++++++++++++++-----
 .../groovy/vmplugin/v16/ProxyMethodHandle.java     | 30 ++++++++++++++++++++++
 .../org/codehaus/groovy/vmplugin/v8/Java8.java     |  1 -
 3 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java b/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
index 1733f0f..8d2e1bb 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
@@ -21,6 +21,7 @@ package org.codehaus.groovy.vmplugin.v16;
 import groovy.lang.GroovyRuntimeException;
 import org.codehaus.groovy.vmplugin.v10.Java10;
 
+import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -50,12 +51,6 @@ public class Java16 extends Java10 {
 
     public static MethodHandles.Lookup of(final Class<?> declaringClass) {
         try {
-            // All proxy classes are not open for reflective access in Java SE 16
-            // See also https://www.oracle.com/java/technologies/javase/16-relnotes.html
-            if (Proxy.isProxyClass(declaringClass)) {
-                return MethodHandles.lookup().in(declaringClass);
-            }
-
             final Method privateLookup = getPrivateLookup();
             if (privateLookup != null) {
                 MethodHandles.Lookup caller = MethodHandles.lookup();
@@ -85,14 +80,31 @@ public class Java16 extends Java10 {
     public Object getInvokeSpecialHandle(Method method, Object receiver) {
         final Class<?> receiverType = receiver.getClass();
         try {
+            if (method.isDefault() && Proxy.isProxyClass(receiverType)) {
+                return new ProxyMethodHandle((Proxy) receiver, method);
+            }
+
             MethodHandles.Lookup lookup = newLookup(receiverType);
-            return lookup.unreflectSpecial(method, receiverType).bindTo(receiver);
+            if (MethodHandles.Lookup.PRIVATE == lookup.lookupModes()) {
+                return lookup.unreflectSpecial(method, receiverType).bindTo(receiver);
+            }
+            return lookup.unreflect(method).bindTo(receiver);
         } catch (ReflectiveOperationException e) {
             return new GroovyRuntimeException(e);
         }
     }
 
     @Override
+    public Object invokeHandle(Object handle, Object[] args) throws Throwable {
+        if (handle instanceof ProxyMethodHandle) {
+            return ((ProxyMethodHandle) handle).invokeWithArguments(args);
+        }
+        if (handle instanceof Throwable) throw (Throwable) handle;
+        MethodHandle mh = (MethodHandle) handle;
+        return mh.invokeWithArguments(args);
+    }
+
+    @Override
     public Class<?>[] getPluginDefaultGroovyMethods() {
         return PLUGIN_DGM;
     }
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v16/ProxyMethodHandle.java b/src/main/java/org/codehaus/groovy/vmplugin/v16/ProxyMethodHandle.java
new file mode 100644
index 0000000..d6a1e39
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v16/ProxyMethodHandle.java
@@ -0,0 +1,30 @@
+package org.codehaus.groovy.vmplugin.v16;
+
+import org.codehaus.groovy.GroovyBugError;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+class ProxyMethodHandle {
+    private static final Method INVOKE_DEFAULT_METHOD;
+    static {
+        try {
+            INVOKE_DEFAULT_METHOD = InvocationHandler.class.getDeclaredMethod("invokeDefault", Object.class, Method.class, Object[].class);
+        } catch (NoSuchMethodException e) {
+            throw new GroovyBugError(e);
+        }
+    }
+
+    private final Proxy proxy;
+    private final Method method;
+
+    ProxyMethodHandle(Proxy proxy, Method method) {
+        this.proxy = proxy;
+        this.method = method;
+    }
+
+    Object invokeWithArguments(Object... arguments) throws Throwable {
+        return INVOKE_DEFAULT_METHOD.invoke(null, proxy, method, arguments);
+    }
+}
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 87a6d40..3f54df0 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
@@ -652,7 +652,6 @@ public class Java8 implements VMPlugin {
 
     @Override
     public Object invokeHandle(Object handle, Object[] args) throws Throwable {
-        if (handle instanceof Throwable) throw (Throwable) handle;
         MethodHandle mh = (MethodHandle) handle;
         return mh.invokeWithArguments(args);
     }