changeset 5975:9efb5fb77027

8009424: Adapt Nashorn to JSR-292 implementation change Reviewed-by: jrose, twisti, jdn, mchung
author vlivanov
date Tue, 09 Apr 2013 17:38:32 +0400
parents 89d9ec9e80c1
children f2d4da9ba0f0
files src/share/classes/java/lang/invoke/MethodHandleNatives.java src/share/classes/java/lang/invoke/MethodHandles.java
diffstat 2 files changed, 40 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Apr 09 15:03:29 2013 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Apr 09 17:38:32 2013 +0400
@@ -431,21 +431,6 @@
             return defc == sun.misc.Unsafe.class;
         case "lookup":
             return defc == java.lang.invoke.MethodHandles.class;
-        case "findStatic":
-        case "findVirtual":
-        case "findConstructor":
-        case "findSpecial":
-        case "findGetter":
-        case "findSetter":
-        case "findStaticGetter":
-        case "findStaticSetter":
-        case "bind":
-        case "unreflect":
-        case "unreflectSpecial":
-        case "unreflectConstructor":
-        case "unreflectGetter":
-        case "unreflectSetter":
-            return defc == java.lang.invoke.MethodHandles.Lookup.class;
         case "invoke":
             return defc == java.lang.reflect.Method.class;
         case "get":
--- a/src/share/classes/java/lang/invoke/MethodHandles.java	Tue Apr 09 15:03:29 2013 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandles.java	Tue Apr 09 17:38:32 2013 +0400
@@ -26,7 +26,6 @@
 package java.lang.invoke;
 
 import java.lang.reflect.*;
-import sun.invoke.WrapperInstance;
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyAccess;
 import sun.invoke.util.Wrapper;
@@ -35,9 +34,11 @@
 import java.util.Arrays;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
-import sun.security.util.SecurityConstants;
+import sun.reflect.misc.ReflectUtil;
+
 import static java.lang.invoke.MethodHandleStatics.*;
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import sun.security.util.SecurityConstants;
 
 /**
  * This class consists exclusively of static methods that operate on or return
@@ -564,13 +565,11 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public
         MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             MemberName method = resolveOrFail(refc, name, type, true);
-            Class<?> callerClass = Reflection.getCallerClass();
-            checkSecurityManager(refc, method, callerClass);
-            return accessStatic(refc, method, findBoundCallerClass(method, callerClass));
+            checkSecurityManager(refc, method);
+            return accessStatic(refc, method, findBoundCallerClass(method));
         }
         private
         MethodHandle accessStatic(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
@@ -623,12 +622,10 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             MemberName method = resolveOrFail(refc, name, type, false);
-            Class<?> callerClass = Reflection.getCallerClass();
-            checkSecurityManager(refc, method, callerClass);
-            return accessVirtual(refc, method, findBoundCallerClass(method, callerClass));
+            checkSecurityManager(refc, method);
+            return accessVirtual(refc, method, findBoundCallerClass(method));
         }
         private MethodHandle resolveVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             MemberName method = resolveOrFail(refc, name, type, false);
@@ -667,11 +664,10 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             String name = "<init>";
             MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
-            checkSecurityManager(refc, ctor, Reflection.getCallerClass());
+            checkSecurityManager(refc, ctor);
             return accessConstructor(refc, ctor);
         }
         private MethodHandle accessConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
@@ -737,14 +733,12 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
                                         Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
             checkSpecialCaller(specialCaller);
             MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
-            Class<?> callerClass = Reflection.getCallerClass();
-            checkSecurityManager(refc, method, callerClass);
-            return accessSpecial(refc, method, findBoundCallerClass(method, callerClass), specialCaller);
+            checkSecurityManager(refc, method);
+            return accessSpecial(refc, method, findBoundCallerClass(method), specialCaller);
         }
         private MethodHandle accessSpecial(Class<?> refc, MemberName method,
                                            Class<?> callerClass,
@@ -801,10 +795,9 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(refc, name, type, false);
-            checkSecurityManager(refc, field, Reflection.getCallerClass());
+            checkSecurityManager(refc, field);
             return makeAccessor(refc, field, false, false, 0);
         }
         private MethodHandle resolveGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
@@ -829,10 +822,9 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(refc, name, type, false);
-            checkSecurityManager(refc, field, Reflection.getCallerClass());
+            checkSecurityManager(refc, field);
             return makeAccessor(refc, field, false, true, 0);
         }
         private MethodHandle resolveSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
@@ -856,10 +848,9 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(refc, name, type, true);
-            checkSecurityManager(refc, field, Reflection.getCallerClass());
+            checkSecurityManager(refc, field);
             return makeAccessor(refc, field, false, false, 1);
         }
         private MethodHandle resolveStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
@@ -883,10 +874,9 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(refc, name, type, true);
-            checkSecurityManager(refc, field, Reflection.getCallerClass());
+            checkSecurityManager(refc, field);
             return makeAccessor(refc, field, false, true, 1);
         }
         private MethodHandle resolveStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
@@ -940,15 +930,13 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             Class<? extends Object> refc = receiver.getClass(); // may get NPE
             MemberName method = resolveOrFail(refc, name, type, false);
-            Class<?> callerClass = Reflection.getCallerClass();
-            checkSecurityManager(refc, method, callerClass);
+            checkSecurityManager(refc, method);
             checkMethod(refc, method, false);
             MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
-            MethodHandle bcmh = maybeBindCaller(method, dmh, findBoundCallerClass(method, callerClass));
+            MethodHandle bcmh = maybeBindCaller(method, dmh, findBoundCallerClass(method));
             if (bcmh != dmh)  return fixVarargs(bcmh.bindTo(receiver), dmh);
             MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver);
             if (bmh == null)
@@ -977,7 +965,6 @@
          *                                is set and {@code asVarargsCollector} fails
          * @throws NullPointerException if the argument is null
          */
-        @CallerSensitive
         public MethodHandle unreflect(Method m) throws IllegalAccessException {
             MemberName method = new MemberName(m);
             assert(method.isMethod());
@@ -985,8 +972,7 @@
                 return MethodHandleImpl.findMethod(method, true, /*no lookupClass*/ null);
             checkMethod(method.getDeclaringClass(), method, method.isStatic());
             MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
-            Class<?> callerClass = Reflection.getCallerClass();
-            mh = maybeBindCaller(method, mh, findBoundCallerClass(method, callerClass));
+            mh = maybeBindCaller(method, mh, findBoundCallerClass(method));
             return restrictProtectedReceiver(method, mh);
         }
 
@@ -1011,7 +997,6 @@
          *                                is set and {@code asVarargsCollector} fails
          * @throws NullPointerException if any argument is null
          */
-        @CallerSensitive
         public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
             checkSpecialCaller(specialCaller);
             MemberName method = new MemberName(m);
@@ -1019,8 +1004,7 @@
             // ignore m.isAccessible:  this is a new kind of access
             checkMethod(m.getDeclaringClass(), method, false);
             MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
-            Class<?> callerClass = Reflection.getCallerClass();
-            mh = maybeBindCaller(method, mh, findBoundCallerClass(method, callerClass));
+            mh = maybeBindCaller(method, mh, findBoundCallerClass(method));
             return restrictReceiver(method, mh, specialCaller);
         }
 
@@ -1132,21 +1116,25 @@
         /**
          * Find my trustable caller class if m is a caller sensitive method.
          * If this lookup object has private access, then the caller class is the lookupClass.
-         * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
+         * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
          */
-        Class<?> findBoundCallerClass(MemberName m, Class<?> caller) {
+        Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
             Class<?> callerClass = null;
             if (MethodHandleNatives.isCallerSensitive(m)) {
-                // Do not refactor this to a more "logical" place, since it is stack walk magic.
-                // Note that this is the same expression as in Step 2 below in checkSecurityManager.
-                callerClass = ((allowedModes & PRIVATE) != 0
-                               ? lookupClass  // for strong access modes, no extra check
-                               // next line does stack walk magic; do not refactor:
-                               : caller);
+                // Only full-power lookup is allowed to resolve caller-sensitive methods
+                if (isFullPowerLookup()) {
+                    callerClass = lookupClass;
+                } else {
+                    throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
+                }
             }
             return callerClass;
         }
 
+        private boolean isFullPowerLookup() {
+            return (allowedModes & PRIVATE) != 0;
+        }
+
         /**
          * Determine whether a security manager has an overridden
          * SecurityManager.checkMemberAccess method.
@@ -1167,7 +1155,7 @@
          * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
          * This function performs stack walk magic: do not refactor it.
          */
-        void checkSecurityManager(Class<?> refc, MemberName m, Class<?> caller) {
+        void checkSecurityManager(Class<?> refc, MemberName m) {
             SecurityManager smgr = System.getSecurityManager();
             if (smgr == null)  return;
             if (allowedModes == TRUSTED)  return;
@@ -1187,13 +1175,10 @@
             }
 
             // Step 2:
-            Class<?> callerClass = ((allowedModes & PRIVATE) != 0
-                                    ? lookupClass  // for strong access modes, no extra check
-                                    : caller);
-            if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) ||
-                (callerClass != lookupClass &&
-                 !VerifyAccess.classLoaderIsAncestor(callerClass, refc)))
-                smgr.checkPackageAccess(VerifyAccess.getPackageName(refc));
+            if (!isFullPowerLookup() ||
+                !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
+                ReflectUtil.checkPackageAccess(refc);
+            }
 
             // Step 3:
             if (m.isPublic()) return;
@@ -1203,7 +1188,8 @@
                 final int which = Member.DECLARED;
                 final Class<?> clazz = defc;
                 if (!overridden) {
-                    if (caller.getClassLoader() != defc.getClassLoader()) {
+                    if (!isFullPowerLookup() ||
+                        (lookupClass.getClassLoader() != defc.getClassLoader())) {
                         smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
                     }
                 } else {
@@ -1214,8 +1200,9 @@
             }
 
             // Step 4:
-            if (defc != refc)
-                smgr.checkPackageAccess(VerifyAccess.getPackageName(defc));
+            if (defc != refc) {
+                ReflectUtil.checkPackageAccess(defc);
+            }
         }
 
         void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {