src/share/classes/java/lang/invoke/MethodHandles.java

Print this page

        

@@ -33,10 +33,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import sun.reflect.Reflection;
 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
  * method handles. They fall into several categories:
  * <ul>

@@ -301,27 +302,21 @@
      * {@code refc} as the containing class in which the member
      * is being sought, and {@code defc} as the class in which the
      * member is actually defined.
      * The calls are made according to the following rules:
      * <ul>
-     * <li>In all cases, {@link SecurityManager#checkMemberAccess
-     *     smgr.checkMemberAccess(refc, Member.PUBLIC)} is called.
      * <li>If the class loader of the lookup class is not
      *     the same as or an ancestor of the class loader of {@code refc},
      *     then {@link SecurityManager#checkPackageAccess
      *     smgr.checkPackageAccess(refcPkg)} is called,
      *     where {@code refcPkg} is the package of {@code refc}.
-     * <li>If the retrieved member is not public,
-     *     {@link SecurityManager#checkMemberAccess
-     *     smgr.checkMemberAccess(defc, Member.DECLARED)} is called.
-     *     (Note that {@code defc} might be the same as {@code refc}.)
-     *     The default implementation of this security manager method
-     *     inspects the stack to determine the original caller of
-     *     the reflective request (such as {@code findStatic}),
-     *     and performs additional permission checks if the
-     *     class loader of {@code defc} differs from the class
-     *     loader of the class from which the reflective request came.
+     * <li>If the retrieved member is not public and
+     *     the class loader of {@code defc} differs from the class
+     *     loader of the class from which the reflective request came
+     *     (such as {@code findStatic}),
+     *     {@link SecurityManager#checkPermission smgr.checkPermission}
+     *     with {@code RuntimePermission("accessDeclaredMembers")} is called.
      * <li>If the retrieved member is not public,
      *     and if {@code defc} and {@code refc} are in different class loaders,
      *     and if the class loader of the lookup class is not
      *     the same as or an ancestor of the class loader of {@code defc},
      *     then {@link SecurityManager#checkPackageAccess

@@ -1074,45 +1069,29 @@
         void checkSecurityManager(Class<?> refc, MemberName m) {
             SecurityManager smgr = System.getSecurityManager();
             if (smgr == null)  return;
             if (allowedModes == TRUSTED)  return;
             // Step 1:
-            smgr.checkMemberAccess(refc, Member.PUBLIC);
-            // Step 2:
             Class<?> callerClass = ((allowedModes & PRIVATE) != 0
                                     ? lookupClass  // for strong access modes, no extra check
                                     // next line does stack walk magic; do not refactor:
                                     : getCallerClassAtEntryPoint(true));
             if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) ||
                 (callerClass != lookupClass &&
                  !VerifyAccess.classLoaderIsAncestor(callerClass, refc)))
                 smgr.checkPackageAccess(VerifyAccess.getPackageName(refc));
-            // Step 3:
+            // Step 2:
             if (m.isPublic()) return;
             Class<?> defc = m.getDeclaringClass();
-            smgr.checkMemberAccess(defc, Member.DECLARED);  // STACK WALK HERE
-            // Step 4:
+            ClassLoader ccl = callerClass != null ? callerClass.getClassLoader() : null;
+            // access Member.DECLARED
+            if (ccl != defc.getClassLoader()) {
+                smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
+            }
+            // Step 3:
             if (defc != refc)
                 smgr.checkPackageAccess(VerifyAccess.getPackageName(defc));
-
-            // Comment from SM.checkMemberAccess, where which=DECLARED:
-            /*
-             * stack depth of 4 should be the caller of one of the
-             * methods in java.lang.Class that invoke checkMember
-             * access. The stack should look like:
-             *
-             * someCaller                        [3]
-             * java.lang.Class.someReflectionAPI [2]
-             * java.lang.Class.checkMemberAccess [1]
-             * SecurityManager.checkMemberAccess [0]
-             *
-             */
-            // For us it is this stack:
-            // someCaller                        [3]
-            // Lookup.findSomeMember             [2]
-            // Lookup.checkSecurityManager       [1]
-            // SecurityManager.checkMemberAccess [0]
         }
 
         void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
             boolean wantStatic = (refKind == REF_invokeStatic);
             String message;