< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


2199             // check the class first:
2200             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201                                (defc == refc ||
2202                                 Modifier.isPublic(refc.getModifiers())));
2203             if (!classOK && (allowedModes & PACKAGE) != 0) {
2204                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205                            (defc == refc ||
2206                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207             }
2208             if (!classOK)
2209                 return "class is not public";
2210             if (Modifier.isPublic(mods))
2211                 return "access to public member failed";  // (how?, module not readable?)
2212             if (Modifier.isPrivate(mods))
2213                 return "member is private";
2214             if (Modifier.isProtected(mods))
2215                 return "member is protected";
2216             return "member is private to package";
2217         }
2218 
2219         private static final boolean ALLOW_NESTMATE_ACCESS = false;
2220 
2221         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2222             int allowedModes = this.allowedModes;
2223             if (allowedModes == TRUSTED)  return;
2224             if (!hasPrivateAccess()
2225                 || (specialCaller != lookupClass()
2226                        // ensure non-abstract methods in superinterfaces can be special-invoked
2227                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
2228                     && !(ALLOW_NESTMATE_ACCESS &&
2229                          VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
2230                 throw new MemberName(specialCaller).
2231                     makeAccessException("no private access for invokespecial", this);
2232         }
2233 
2234         private boolean restrictProtectedReceiver(MemberName method) {
2235             // The accessing class only has the right to use a protected member
2236             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2237             if (!method.isProtected() || method.isStatic()
2238                 || allowedModes == TRUSTED
2239                 || method.getDeclaringClass() == lookupClass()
2240                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
2241                 || (ALLOW_NESTMATE_ACCESS &&
2242                     VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
2243                 return false;
2244             return true;
2245         }
2246         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2247             assert(!method.isStatic());
2248             // receiver type of mh is too wide; narrow to caller
2249             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2250                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2251             }
2252             MethodType rawType = mh.type();
2253             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2254             MethodType narrowType = rawType.changeParameterType(0, caller);
2255             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2256             assert(mh.viewAsTypeChecks(narrowType, true));
2257             return mh.copyWith(narrowType, mh.form);
2258         }
2259 
2260         /** Check access and get the requested method. */
2261         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2262             final boolean doRestrict    = true;
2263             final boolean checkSecurity = true;
2264             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
2265         }
2266         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
2267         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2268             final boolean doRestrict    = false;
2269             final boolean checkSecurity = true;
2270             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerClass);
2271         }
2272         /** Check access and get the requested method, eliding security manager checks. */
2273         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2274             final boolean doRestrict    = true;
2275             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
2276             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
2277         }
2278         /** Common code for all methods; do not call directly except from immediately above. */
2279         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
2280                                                    boolean checkSecurity,
2281                                                    boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {

2282             checkMethod(refKind, refc, method);
2283             // Optionally check with the security manager; this isn't needed for unreflect* calls.
2284             if (checkSecurity)
2285                 checkSecurityManager(refc, method);
2286             assert(!method.isMethodHandleInvoke());
2287 
2288             if (refKind == REF_invokeSpecial &&
2289                 refc != lookupClass() &&
2290                 !refc.isInterface() &&
2291                 refc != lookupClass().getSuperclass() &&
2292                 refc.isAssignableFrom(lookupClass())) {
2293                 assert(!method.getName().equals("<init>"));  // not this code path

2294                 // Per JVMS 6.5, desc. of invokespecial instruction:
2295                 // If the method is in a superclass of the LC,
2296                 // and if our original search was above LC.super,
2297                 // repeat the search (symbolic lookup) from LC.super
2298                 // and continue with the direct superclass of that class,
2299                 // and so forth, until a match is found or no further superclasses exist.
2300                 // FIXME: MemberName.resolve should handle this instead.
2301                 Class<?> refcAsSuper = lookupClass();
2302                 MemberName m2;
2303                 do {
2304                     refcAsSuper = refcAsSuper.getSuperclass();
2305                     m2 = new MemberName(refcAsSuper,
2306                                         method.getName(),
2307                                         method.getMethodType(),
2308                                         REF_invokeSpecial);
2309                     m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
2310                 } while (m2 == null &&         // no method is found yet
2311                          refc != refcAsSuper); // search up to refc
2312                 if (m2 == null)  throw new InternalError(method.toString());
2313                 method = m2;


   1 /*
   2  * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


2199             // check the class first:
2200             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201                                (defc == refc ||
2202                                 Modifier.isPublic(refc.getModifiers())));
2203             if (!classOK && (allowedModes & PACKAGE) != 0) {
2204                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205                            (defc == refc ||
2206                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207             }
2208             if (!classOK)
2209                 return "class is not public";
2210             if (Modifier.isPublic(mods))
2211                 return "access to public member failed";  // (how?, module not readable?)
2212             if (Modifier.isPrivate(mods))
2213                 return "member is private";
2214             if (Modifier.isProtected(mods))
2215                 return "member is protected";
2216             return "member is private to package";
2217         }
2218 


2219         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2220             int allowedModes = this.allowedModes;
2221             if (allowedModes == TRUSTED)  return;
2222             if (!hasPrivateAccess()
2223                 || (specialCaller != lookupClass()
2224                        // ensure non-abstract methods in superinterfaces can be special-invoked
2225                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))


2226                 throw new MemberName(specialCaller).
2227                     makeAccessException("no private access for invokespecial", this);
2228         }
2229 
2230         private boolean restrictProtectedReceiver(MemberName method) {
2231             // The accessing class only has the right to use a protected member
2232             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2233             if (!method.isProtected() || method.isStatic()
2234                 || allowedModes == TRUSTED
2235                 || method.getDeclaringClass() == lookupClass()
2236                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))


2237                 return false;
2238             return true;
2239         }
2240         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2241             assert(!method.isStatic());
2242             // receiver type of mh is too wide; narrow to caller
2243             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2244                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2245             }
2246             MethodType rawType = mh.type();
2247             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2248             MethodType narrowType = rawType.changeParameterType(0, caller);
2249             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2250             assert(mh.viewAsTypeChecks(narrowType, true));
2251             return mh.copyWith(narrowType, mh.form);
2252         }
2253 
2254         /** Check access and get the requested method. */
2255         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2256             final boolean doRestrict    = true;
2257             final boolean checkSecurity = true;
2258             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
2259         }
2260         /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
2261         private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2262             final boolean doRestrict    = false;
2263             final boolean checkSecurity = true;
2264             return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerClass);
2265         }
2266         /** Check access and get the requested method, eliding security manager checks. */
2267         private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2268             final boolean doRestrict    = true;
2269             final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
2270             return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
2271         }
2272         /** Common code for all methods; do not call directly except from immediately above. */
2273         private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
2274                                                    boolean checkSecurity,
2275                                                    boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
2276 
2277             checkMethod(refKind, refc, method);
2278             // Optionally check with the security manager; this isn't needed for unreflect* calls.
2279             if (checkSecurity)
2280                 checkSecurityManager(refc, method);
2281             assert(!method.isMethodHandleInvoke());
2282 
2283             if (refKind == REF_invokeSpecial &&
2284                 refc != lookupClass() &&
2285                 !refc.isInterface() &&
2286                 refc != lookupClass().getSuperclass() &&
2287                 refc.isAssignableFrom(lookupClass())) {
2288                 assert(!method.getName().equals("<init>"));  // not this code path
2289 
2290                 // Per JVMS 6.5, desc. of invokespecial instruction:
2291                 // If the method is in a superclass of the LC,
2292                 // and if our original search was above LC.super,
2293                 // repeat the search (symbolic lookup) from LC.super
2294                 // and continue with the direct superclass of that class,
2295                 // and so forth, until a match is found or no further superclasses exist.
2296                 // FIXME: MemberName.resolve should handle this instead.
2297                 Class<?> refcAsSuper = lookupClass();
2298                 MemberName m2;
2299                 do {
2300                     refcAsSuper = refcAsSuper.getSuperclass();
2301                     m2 = new MemberName(refcAsSuper,
2302                                         method.getName(),
2303                                         method.getMethodType(),
2304                                         REF_invokeSpecial);
2305                     m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
2306                 } while (m2 == null &&         // no method is found yet
2307                          refc != refcAsSuper); // search up to refc
2308                 if (m2 == null)  throw new InternalError(method.toString());
2309                 method = m2;


< prev index next >