You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by GitBox <gi...@apache.org> on 2018/12/27 06:53:55 UTC

[GitHub] asfgit closed pull request #811: GROOVY-8843: Fix illegal reflective access within o.c.g.vmplugin.v7.J…

asfgit closed pull request #811: GROOVY-8843: Fix illegal reflective access within o.c.g.vmplugin.v7.J…
URL: https://github.com/apache/groovy/pull/811
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/build.gradle b/build.gradle
index b36eb5506b..36db7ba0f6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -414,11 +414,11 @@ task checkCompatibility {
     }
 }
 
-if (!JavaVersion.current().java8Compatible) {
+if (!JavaVersion.current().java9Compatible) {
     logger.lifecycle '''
     **************************************** WARNING ********************************************
-    ******   You are running the build with an older JDK. NEVER try to release with 1.7.   ******
-    ******   You must use a JDK 1.8+ in order to compile all features of the language.     ******
+    ******   You are running the build with an older JDK. NEVER try to release with 1.8.   ******
+    ******   You must use a JDK 1.9+ in order to compile all features of the language.     ******
     *********************************************************************************************
 '''
 }
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java
index 11a20911b6..8694d38da5 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java
@@ -29,40 +29,44 @@
 import java.security.PrivilegedAction;
 
 /**
- * Java 7 based functions. Currently just a stub but you can
- * add your own methods to your own version and place it on the classpath
- * ahead of this one.
+ * Java 7 based functions.
  *
- * @author Jochen Theodorou
+ * For crude customization, you can add your own methods to your own version and place it on the classpath ahead of this one.
  */
 public class Java7 extends Java6 {
-    private static final Constructor<MethodHandles.Lookup> LOOKUP_Constructor;
-    static {
-        Constructor<MethodHandles.Lookup> con = null;
-        try {
-            con = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
-        } catch (NoSuchMethodException e) {
-            throw new GroovyBugError(e);
-        }
-        try {
-            if (!con.isAccessible()) {
-                final Constructor tmp = con;
-                AccessController.doPrivileged(new PrivilegedAction() {
-                    @Override
-                    public Object run() {
-                        tmp.setAccessible(true);
-                        return null;
-                    }
-                });
+    private static class LookupHolder {
+        private static final Constructor<MethodHandles.Lookup> LOOKUP_Constructor;
+        static {
+            Constructor<MethodHandles.Lookup> con = null;
+            try {
+                con = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
+            } catch (NoSuchMethodException e) {
+                throw new GroovyBugError(e);
             }
-        } catch (SecurityException se) {
-            con = null;
-        } catch (RuntimeException re) {
-            // test for JDK9 JIGSAW
-            if (!"java.lang.reflect.InaccessibleObjectException".equals(re.getClass().getName())) throw re;
-            con = null;
+            try {
+                if (!con.isAccessible()) {
+                    final Constructor tmp = con;
+                    AccessController.doPrivileged(new PrivilegedAction() {
+                        @Override
+                        public Object run() {
+                            tmp.setAccessible(true);
+                            return null;
+                        }
+                    });
+                }
+            } catch (SecurityException se) {
+                con = null;
+            } catch (RuntimeException re) {
+                // test for JDK9 JIGSAW
+                if (!"java.lang.reflect.InaccessibleObjectException".equals(re.getClass().getName())) throw re;
+                con = null;
+            }
+            LOOKUP_Constructor = con;
         }
-        LOOKUP_Constructor = con;
+    }
+
+    private static Constructor<MethodHandles.Lookup> getLookupConstructor() {
+        return LookupHolder.LOOKUP_Constructor;
     }
 
     @Override
@@ -77,7 +81,7 @@ public int getVersion() {
 
     @Override
     public Object getInvokeSpecialHandle(final Method method, final Object receiver) {
-        if (LOOKUP_Constructor==null) {
+        if (getLookupConstructor() == null) {
             return super.getInvokeSpecialHandle(method, receiver);
         }
         if (!method.isAccessible()) {
@@ -91,8 +95,7 @@ public Object run() {
         }
         Class declaringClass = method.getDeclaringClass();
         try {
-            return LOOKUP_Constructor.
-                    newInstance(declaringClass, -1).
+            return getLookupConstructor().newInstance(declaringClass, -1).
                     unreflectSpecial(method, declaringClass).
                     bindTo(receiver);
         } catch (ReflectiveOperationException e) {
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java b/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
index 74685813f2..290a654fab 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
@@ -18,14 +18,78 @@
  */
 package org.codehaus.groovy.vmplugin.v9;
 
+import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.vmplugin.v8.Java8;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
 /**
- * Java 9 based functions will be added here if needed.
+ * Additional Java 9 based functions will be added here as needed.
  */
 public class Java9 extends Java8 {
+
+    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
+                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()) {
+                        lookup.setAccessible(true);
+                    }
+                } catch (final NoSuchMethodException ex) {
+                    throw new IllegalStateException("Incompatible JVM", e);
+                }
+            }
+            PRIVATE_LOOKUP = privateLookup;
+            LOOKUP_Constructor = lookup;
+        }
+    }
+
+    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 {
+            if (getPrivateLookup() != null) {
+                return MethodHandles.Lookup.class.cast(getPrivateLookup().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 RuntimeException(e);
+        }
+    }
+
     @Override
     public int getVersion() {
         return 9;
     }
+
+    @Override
+    public Object getInvokeSpecialHandle(Method method, Object receiver) {
+        if (getLookupConstructor() != null) {
+            Class declaringClass = method.getDeclaringClass();
+            try {
+                return of(declaringClass).unreflectSpecial(method, receiver.getClass()).bindTo(receiver);
+            } catch (ReflectiveOperationException e) {
+                throw new GroovyBugError(e);
+            }
+        }
+        return super.getInvokeSpecialHandle(method, receiver);
+    }
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services