OpenJDK / portola / portola
changeset 20534:da86f7904e6d
8025112: JSR 292 spec updates for security manager and caller sensitivity
Summary: align CONSTANT_MethodHandle and Lookup.find* API calls, clarify security manager & @CallerSensitive interactions
Reviewed-by: mchung, twisti
author | jrose |
---|---|
date | Sat, 05 Oct 2013 05:30:39 -0700 |
parents | bee974bc42ac |
children | cc85c8626435 |
files | jdk/src/share/classes/java/lang/invoke/MethodHandle.java jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java jdk/src/share/classes/java/lang/invoke/MethodHandles.java jdk/test/java/lang/invoke/TestPrivateMember.java |
diffstat | 6 files changed, 170 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Sat Oct 05 05:30:39 2013 -0700 @@ -1331,6 +1331,11 @@ } /*non-public*/ + Class<?> internalCallerClass() { + return null; // caller-bound MH for @CallerSensitive method returns caller + } + + /*non-public*/ MethodHandle withInternalMemberName(MemberName member) { if (member != null) { return MethodHandleImpl.makeWrappedMember(this, member);
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Sat Oct 05 05:30:39 2013 -0700 @@ -381,6 +381,10 @@ MemberName internalMemberName() { return asFixedArity().internalMemberName(); } + @Override + Class<?> internalCallerClass() { + return asFixedArity().internalCallerClass(); + } /*non-public*/ @Override @@ -831,7 +835,7 @@ MethodHandle vamh = prepareForInvoker(mh); // Cache the result of makeInjectedInvoker once per argument class. MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); - return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName()); + return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass); } private static MethodHandle makeInjectedInvoker(Class<?> hostClass) { @@ -886,10 +890,12 @@ } // Undo the adapter effect of prepareForInvoker: - private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, MemberName member) { + private static MethodHandle restoreToType(MethodHandle vamh, MethodType type, + MemberName member, + Class<?> hostClass) { MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount()); mh = mh.asType(type); - mh = mh.withInternalMemberName(member); + mh = new WrappedMember(mh, type, member, hostClass); return mh; } @@ -958,11 +964,13 @@ static class WrappedMember extends MethodHandle { private final MethodHandle target; private final MemberName member; + private final Class<?> callerClass; - private WrappedMember(MethodHandle target, MethodType type, MemberName member) { + private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) { super(type, reinvokerForm(target)); this.target = target; this.member = member; + this.callerClass = callerClass; } @Override @@ -980,19 +988,23 @@ return member; } @Override + Class<?> internalCallerClass() { + return callerClass; + } + @Override boolean isInvokeSpecial() { return target.isInvokeSpecial(); } @Override MethodHandle viewAsType(MethodType newType) { - return new WrappedMember(target, newType, member); + return new WrappedMember(target, newType, member, callerClass); } } static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) { if (member.equals(target.internalMemberName())) return target; - return new WrappedMember(target, target.type(), member); + return new WrappedMember(target, target.type(), member, null); } }
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java Sat Oct 05 05:30:39 2013 -0700 @@ -61,6 +61,18 @@ * Cracking must be done via a {@code Lookup} object equivalent to that which created * the target method handle, or which has enough access permissions to recreate * an equivalent method handle. + * <p> + * If the underlying method is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>, + * the direct method handle will have been "bound" to a particular caller class, the + * {@linkplain java.lang.invoke.MethodHandles.Lookup#lookupClass() lookup class} + * of the lookup object used to create it. + * Cracking this method handle with a different lookup class will fail + * even if the underlying method is public (like {@code Class.forName}). + * <p> + * The requirement of lookup object matching provides a "fast fail" behavior + * for programs which may otherwise trust erroneous revelation of a method + * handle with symbolic information (or caller binding) from an unexpected scope. + * Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation. * * <h1><a name="refkinds"></a>Reference kinds</h1> * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Sat Oct 05 05:30:39 2013 -0700 @@ -107,6 +107,11 @@ * such as abstract classes with single abstract methods. * Future versions of this API may also equip wrapper instances * with one or more additional public "marker" interfaces. + * <p> + * If a security manager is installed, this method is caller sensitive. + * During any invocation of the target method handle via the returned wrapper, + * the original creator of the wrapper (the caller) will be visible + * to context checks requested by the security manager. * * @param <T> the desired type of the wrapper, a single-method interface * @param intfc a class object representing {@code T}
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:39 2013 -0700 @@ -90,6 +90,10 @@ * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}. * Since all classes have equal access to public names, * such a change would confer no new access rights. + * A public lookup object is always subject to + * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>. + * Also, it cannot access + * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>. * @return a lookup object which is trusted minimally */ public static Lookup publicLookup() { @@ -242,9 +246,9 @@ * For example, lookups for {@code MethodHandle.invokeExact} and * {@code MethodHandle.invoke} will always succeed, regardless of requested type. * <li>If there is a security manager installed, it can forbid the lookup - * on various grounds (<a href="#secmgr">see below</a>). - * By contrast, the {@code ldc} instruction is not subject to - * security manager checks. + * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>). + * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle} + * constant is not subject to security manager checks. * <li>If the looked-up method has a * <a href="MethodHandle.html#maxarity">very large arity</a>, * the method handle creation may fail, due to the method handle @@ -374,13 +378,42 @@ * {@link SecurityManager#checkPermission smgr.checkPermission} * with {@code RuntimePermission("accessDeclaredMembers")} is called. * <li>If the retrieved member is not public, + * and if {@code lookc} is not present, * and if {@code defc} and {@code refc} are different, * then {@link SecurityManager#checkPackageAccess * smgr.checkPackageAccess(defcPkg)} is called, * where {@code defcPkg} is the package of {@code defc}. * </ul> + * Security checks are performed after other access checks have passed. + * Therefore, the above rules presuppose a member that is public, + * or else that is being accessed from a lookup class that has + * rights to access the member. + * + * <h1><a name="callsens"></a>Caller sensitive methods</h1> + * A small number of Java methods have a special property called caller sensitivity. + * A <em>caller-sensitive</em> method can behave differently depending on the + * identity of its immediate caller. + * <p> + * If a method handle for a caller-sensitive method is requested, + * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply, + * but they take account of the lookup class in a special way. + * The resulting method handle behaves as if it were called + * from an instruction contained in the lookup class, + * so that the caller-sensitive method detects the lookup class. + * (By contrast, the invoker of the method handle is disregarded.) + * Thus, in the case of caller-sensitive methods, + * different lookup classes may give rise to + * differently behaving method handles. + * <p> + * In cases where the lookup object is + * {@link MethodHandles#publicLookup() publicLookup()}, + * or some other lookup object without + * {@linkplain java.lang.invoke.MethodHandles.Lookup#PRIVATE private access}, + * the lookup class is disregarded. + * In such cases, no caller-sensitive method handle can be created, + * access is forbidden, and the lookup fails with an + * {@code IllegalAccessException}. */ - // FIXME in MR1: clarify that the bytecode behavior of a caller-ID method (like Class.forName) is relative to the lookupClass used to create the method handle, not the dynamic caller of the method handle public static final class Lookup { /** The class on behalf of whom the lookup is being performed. */ @@ -639,7 +672,6 @@ public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); - checkSecurityManager(refc, method); return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method)); } @@ -721,7 +753,6 @@ } byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); - checkSecurityManager(refc, method); return getDirectMethod(refKind, refc, method, findBoundCallerClass(method)); } private MethodHandle findVirtualForMH(String name, MethodType type) { @@ -782,7 +813,6 @@ public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = "<init>"; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); - checkSecurityManager(refc, ctor); return getDirectConstructor(refc, ctor); } @@ -864,7 +894,6 @@ checkSpecialCaller(specialCaller); Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); - checkSecurityManager(refc, method); return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); } @@ -887,7 +916,6 @@ */ public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getField, refc, name, type); - checkSecurityManager(refc, field); return getDirectField(REF_getField, refc, field); } @@ -910,7 +938,6 @@ */ public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putField, refc, name, type); - checkSecurityManager(refc, field); return getDirectField(REF_putField, refc, field); } @@ -935,7 +962,6 @@ */ public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getStatic, refc, name, type); - checkSecurityManager(refc, field); return getDirectField(REF_getStatic, refc, field); } @@ -960,7 +986,6 @@ */ public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putStatic, refc, name, type); - checkSecurityManager(refc, field); return getDirectField(REF_putStatic, refc, field); } @@ -1013,7 +1038,6 @@ public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class<? extends Object> refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); - checkSecurityManager(refc, method); MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); return mh.bindReceiver(receiver).setVarargs(method); } @@ -1054,7 +1078,7 @@ refKind = REF_invokeVirtual; assert(method.isMethod()); Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); + return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); } private MethodHandle unreflectForMH(Method m) { // these names require special lookups because they throw UnsupportedOperationException @@ -1090,7 +1114,7 @@ MemberName method = new MemberName(m, true); assert(method.isMethod()); // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); + return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method)); } /** @@ -1122,7 +1146,7 @@ MemberName ctor = new MemberName(c); assert(ctor.isConstructor()); Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectConstructor(ctor.getDeclaringClass(), ctor); + return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor); } /** @@ -1152,7 +1176,7 @@ ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind()) : MethodHandleNatives.refKindIsGetter(field.getReferenceKind())); Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectField(field.getReferenceKind(), f.getDeclaringClass(), field); + return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field); } /** @@ -1183,6 +1207,8 @@ * is capable of reproducing the target method handle. * This means that the cracking may fail if target is a direct method handle * but was created by an unrelated lookup object. + * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> + * and was created by a lookup object for a different class. * @param target a direct method handle to crack into symbolic reference components * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object * @exception SecurityException if a security manager is present and it @@ -1208,11 +1234,16 @@ refKind = REF_invokeInterface; // Check SM permissions and member access before cracking. try { + checkAccess(refKind, defc, member); checkSecurityManager(defc, member); - checkAccess(refKind, defc, member); } catch (IllegalAccessException ex) { throw new IllegalArgumentException(ex); } + if (allowedModes != TRUSTED && member.isCallerSensitive()) { + Class<?> callerClass = target.internalCallerClass(); + if (!hasPrivateAccess() || callerClass != lookupClass()) + throw new IllegalArgumentException("method handle is caller sensitive: "+callerClass); + } // Produce the handle to the results. return new InfoFromMemberName(this, member, refKind); } @@ -1266,8 +1297,8 @@ Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException { Class<?> callerClass = null; if (MethodHandleNatives.isCallerSensitive(m)) { - // Only full-power lookup is allowed to resolve caller-sensitive methods - if (isFullPowerLookup()) { + // Only lookups with private access are allowed to resolve caller-sensitive methods + if (hasPrivateAccess()) { callerClass = lookupClass; } else { throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object"); @@ -1276,7 +1307,7 @@ return callerClass; } - private boolean isFullPowerLookup() { + private boolean hasPrivateAccess() { return (allowedModes & PRIVATE) != 0; } @@ -1291,22 +1322,21 @@ if (allowedModes == TRUSTED) return; // Step 1: - if (!isFullPowerLookup() || + boolean fullPowerLookup = hasPrivateAccess(); + if (!fullPowerLookup || !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { ReflectUtil.checkPackageAccess(refc); } // Step 2: if (m.isPublic()) return; - Class<?> defc = m.getDeclaringClass(); - { - if (!isFullPowerLookup()) { - smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } + if (!fullPowerLookup) { + smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); } // Step 3: - if (defc != refc) { + Class<?> defc = m.getDeclaringClass(); + if (!fullPowerLookup && defc != refc) { ReflectUtil.checkPackageAccess(defc); } } @@ -1335,6 +1365,7 @@ throw m.makeAccessException(message, this); } + /** Check public/protected/private bits on the symbolic reference class and its member. */ void checkAccess(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException { assert(m.referenceKindIsConsistentWith(refKind) && MethodHandleNatives.refKindIsValid(refKind) && @@ -1409,7 +1440,7 @@ private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException { int allowedModes = this.allowedModes; if (allowedModes == TRUSTED) return; - if ((allowedModes & PRIVATE) == 0 + if (!hasPrivateAccess() || (specialCaller != lookupClass() && !(ALLOW_NESTMATE_ACCESS && VerifyAccess.isSamePackageMember(specialCaller, lookupClass())))) @@ -1441,18 +1472,32 @@ return mh.viewAsType(narrowType); } + /** Check access and get the requested method. */ private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { - return getDirectMethodCommon(refKind, refc, method, - (refKind == REF_invokeSpecial || - (MethodHandleNatives.refKindHasReceiver(refKind) && - restrictProtectedReceiver(method))), callerClass); + final boolean doRestrict = true; + final boolean checkSecurity = true; + return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); + } + /** Check access and get the requested method, eliding receiver narrowing rules. */ + private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { + final boolean doRestrict = false; + final boolean checkSecurity = true; + return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); } - private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { - return getDirectMethodCommon(refKind, refc, method, false, callerClass); + /** Check access and get the requested method, eliding security manager checks. */ + private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { + final boolean doRestrict = true; + final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants + return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass); } + /** 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<?> callerClass) 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()); Class<?> refcAsSuper; @@ -1482,7 +1527,11 @@ MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); mh = maybeBindCaller(method, mh, callerClass); mh = mh.setVarargs(method); - if (doRestrict) + // Optionally narrow the receiver argument to refc using restrictReceiver. + if (doRestrict && + (refKind == REF_invokeSpecial || + (MethodHandleNatives.refKindHasReceiver(refKind) && + restrictProtectedReceiver(method)))) mh = restrictReceiver(method, mh, lookupClass()); return mh; } @@ -1492,14 +1541,29 @@ if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) return mh; Class<?> hostClass = lookupClass; - if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup + if (!hasPrivateAccess()) // caller must have private access hostClass = callerClass; // callerClass came from a security manager style stack walk MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); // Note: caller will apply varargs after this step happens. return cbmh; } + /** Check access and get the requested field. */ private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException { + final boolean checkSecurity = true; + return getDirectFieldCommon(refKind, refc, field, checkSecurity); + } + /** Check access and get the requested field, eliding security manager checks. */ + private MethodHandle getDirectFieldNoSecurityManager(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException { + final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants + return getDirectFieldCommon(refKind, refc, field, checkSecurity); + } + /** Common code for all fields; do not call directly except from immediately above. */ + private MethodHandle getDirectFieldCommon(byte refKind, Class<?> refc, MemberName field, + boolean checkSecurity) throws IllegalAccessException { checkField(refKind, refc, field); + // Optionally check with the security manager; this isn't needed for unreflect* calls. + if (checkSecurity) + checkSecurityManager(refc, field); MethodHandle mh = DirectMethodHandle.make(refc, field); boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(field)); @@ -1507,9 +1571,24 @@ mh = restrictReceiver(field, mh, lookupClass()); return mh; } + /** Check access and get the requested constructor. */ private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException { + final boolean checkSecurity = true; + return getDirectConstructorCommon(refc, ctor, checkSecurity); + } + /** Check access and get the requested constructor, eliding security manager checks. */ + private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException { + final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants + return getDirectConstructorCommon(refc, ctor, checkSecurity); + } + /** Common code for all constructors; do not call directly except from immediately above. */ + private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor, + boolean checkSecurity) throws IllegalAccessException { assert(ctor.isConstructor()); checkAccess(REF_newInvokeSpecial, refc, ctor); + // Optionally check with the security manager; this isn't needed for unreflect* calls. + if (checkSecurity) + checkSecurityManager(refc, ctor); assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here return DirectMethodHandle.make(ctor).setVarargs(ctor); } @@ -1527,7 +1606,7 @@ return mh; } MemberName resolved = resolveOrFail(refKind, member); - mh = getDirectMethodHandle(refKind, defc, resolved); + mh = getDirectMethodForConstant(refKind, defc, resolved); if (mh instanceof DirectMethodHandle && canBeCached(refKind, defc, resolved)) { MemberName key = mh.internalMemberName(); @@ -1573,13 +1652,14 @@ return true; } private - MethodHandle getDirectMethodHandle(byte refKind, Class<?> defc, MemberName member) throws ReflectiveOperationException { + MethodHandle getDirectMethodForConstant(byte refKind, Class<?> defc, MemberName member) + throws ReflectiveOperationException { if (MethodHandleNatives.refKindIsField(refKind)) { - return getDirectField(refKind, defc, member); + return getDirectFieldNoSecurityManager(refKind, defc, member); } else if (MethodHandleNatives.refKindIsMethod(refKind)) { - return getDirectMethod(refKind, defc, member, lookupClass); + return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass); } else if (refKind == REF_newInvokeSpecial) { - return getDirectConstructor(defc, member); + return getDirectConstructorNoSecurityManager(defc, member); } // oops throw newIllegalArgumentException("bad MethodHandle constant #"+member);
--- a/jdk/test/java/lang/invoke/TestPrivateMember.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/test/java/lang/invoke/TestPrivateMember.java Sat Oct 05 05:30:39 2013 -0700 @@ -47,7 +47,10 @@ MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodType mt = MethodType.methodType(void.class); try { - MethodHandle mh = lookup.findStatic(Class.class, "checkInitted", mt); + Class<?> checkInittedHolder = TestPrivateMemberPackageSibling.class; + // Original model: checkInittedHolder = Class.class; + // Not using Class.checkInitted because it could change without notice. + MethodHandle mh = lookup.findStatic(checkInittedHolder, "checkInitted", mt); throw new RuntimeException("IllegalAccessException not thrown"); } catch (IllegalAccessException e) { // okay @@ -55,3 +58,7 @@ } } } + +class TestPrivateMemberPackageSibling { + private static void checkInitted() { } +}