< prev index next >

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

Print this page

        

@@ -467,19 +467,24 @@
      * with special names ({@code "<init>"} and {@code "<clinit>"}).
      * The internal syntax of invocation instructions allows them to refer to such internal
      * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
      * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
      * <p>
-     * In some cases, access between nested classes is obtained by the Java compiler by creating
-     * an wrapper method to access a private method of another class
-     * in the same top-level declaration.
+     * If the relationship between nested types is expressed directly through the
+     * {@code NestHost} and {@code NestMembers} attributes
+     * (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29),
+     * then the associated {@code Lookup} object provides direct access to
+     * the lookup class and all of its nestmates
+     * (see {@link java.lang.Class#getNestHost Class.getNestHost}).
+     * Otherwise, access between nested classes is obtained by the Java compiler creating
+     * a wrapper method to access a private method of another class in the same nest.
      * For example, a nested class {@code C.D}
      * can access private members within other related classes such as
      * {@code C}, {@code C.D.E}, or {@code C.B},
      * but the Java compiler may need to generate wrapper methods in
      * those related classes.  In such cases, a {@code Lookup} object on
-     * {@code C.E} would be unable to those private members.
+     * {@code C.E} would be unable to access those private members.
      * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
      * which can transform a lookup on {@code C.E} into one on any of those other
      * classes, without special elevation of privilege.
      * <p>
      * The accesses permitted to a given lookup object may be limited,

@@ -497,15 +502,16 @@
      * <p style="font-size:smaller;">
      * <a id="privacc"></a>
      * <em>Discussion of private access:</em>
      * We say that a lookup has <em>private access</em>
      * if its {@linkplain #lookupModes lookup modes}
-     * include the possibility of accessing {@code private} members.
+     * include the possibility of accessing {@code private} members
+     * (which includes the private members of nestmates).
      * As documented in the relevant methods elsewhere,
      * only lookups with private access possess the following capabilities:
      * <ul style="font-size:smaller;">
-     * <li>access private fields, methods, and constructors of the lookup class
+     * <li>access private fields, methods, and constructors of the lookup class and its nestmates
      * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
      *     such as {@code Class.forName}
      * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
      * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
      *     for classes accessible to the lookup class

@@ -726,13 +732,11 @@
          *  {@linkplain #MODULE MODULE (0x10)},
          *  and {@linkplain #UNCONDITIONAL UNCONDITIONAL (0x20)}.
          *  <p>
          *  A freshly-created lookup object
          *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
-         *  all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to
-         *  access all members of the caller's class, all public types in the caller's module,
-         *  and all public types in packages exported by other modules to the caller's module.
+         *  all possible bits set, except {@code UNCONDITIONAL}.
          *  A lookup object on a new lookup class
          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
          *  may have some mode bits set to zero.
          *  Mode bits can also be
          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.

@@ -1104,12 +1108,13 @@
          * The type of the method handle will be that of the method,
          * with the receiver type (usually {@code refc}) prepended.
          * The method and all its argument types must be accessible to the lookup object.
          * <p>
          * When called, the handle will treat the first argument as a receiver
-         * and dispatch on the receiver's type to determine which method
+         * and, for non-private methods, dispatch on the receiver's type to determine which method
          * implementation to enter.
+         * For private methods the named method in {@code refc} will be invoked on the receiver.
          * (The dispatching action is identical with that performed by an
          * {@code invokevirtual} or {@code invokeinterface} instruction.)
          * <p>
          * The first argument will be of type {@code refc} if the lookup
          * class has full privileges to access the member.  Otherwise

@@ -1169,11 +1174,10 @@
          * @param type the type of the method, with the receiver argument omitted
          * @return the desired method handle
          * @throws NoSuchMethodException if the method does not exist
          * @throws IllegalAccessException if access checking fails,
          *                                or if the method is {@code static},
-         *                                or if the method is {@code private} method of interface,
          *                                or if the method's variable arity modifier bit
          *                                is set and {@code asVarargsCollector} fails
          * @exception SecurityException if a security manager is present and it
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null

@@ -2223,34 +2227,28 @@
             if (Modifier.isProtected(mods))
                 return "member is protected";
             return "member is private to package";
         }
 
-        private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
             int allowedModes = this.allowedModes;
             if (allowedModes == TRUSTED)  return;
             if (!hasPrivateAccess()
                 || (specialCaller != lookupClass()
                        // ensure non-abstract methods in superinterfaces can be special-invoked
-                    && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
-                    && !(ALLOW_NESTMATE_ACCESS &&
-                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
+                    && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))
                 throw new MemberName(specialCaller).
                     makeAccessException("no private access for invokespecial", this);
         }
 
         private boolean restrictProtectedReceiver(MemberName method) {
             // The accessing class only has the right to use a protected member
             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
             if (!method.isProtected() || method.isStatic()
                 || allowedModes == TRUSTED
                 || method.getDeclaringClass() == lookupClass()
-                || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
-                || (ALLOW_NESTMATE_ACCESS &&
-                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
+                || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))
                 return false;
             return true;
         }
         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
             assert(!method.isStatic());

@@ -2286,10 +2284,11 @@
         }
         /** Common code for all methods; do not call directly except from immediately above. */
         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
                                                    boolean checkSecurity,
                                                    boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {
+
             checkMethod(refKind, refc, method);
             // Optionally check with the security manager; this isn't needed for unreflect* calls.
             if (checkSecurity)
                 checkSecurityManager(refc, method);
             assert(!method.isMethodHandleInvoke());

@@ -2298,10 +2297,11 @@
                 refc != lookupClass() &&
                 !refc.isInterface() &&
                 refc != lookupClass().getSuperclass() &&
                 refc.isAssignableFrom(lookupClass())) {
                 assert(!method.getName().equals("<init>"));  // not this code path
+
                 // Per JVMS 6.5, desc. of invokespecial instruction:
                 // If the method is in a superclass of the LC,
                 // and if our original search was above LC.super,
                 // repeat the search (symbolic lookup) from LC.super
                 // and continue with the direct superclass of that class,
< prev index next >