Mercurial > hg > release > icedtea7-forest-2.1 > jdk
changeset 4927:777c7be511a7
8009424: Adapt Nashorn to JSR-292 implementation change
Reviewed-by: jrose, twisti, jdn, mchung
author | andrew |
---|---|
date | Wed, 12 Jun 2013 15:16:26 +0100 |
parents | d5b0fafe5008 |
children | a2a7730dff8a |
files | src/share/classes/java/lang/invoke/MethodHandleNatives.java src/share/classes/java/lang/invoke/MethodHandles.java |
diffstat | 2 files changed, 66 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Mon Apr 08 21:17:57 2013 +0100 +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Jun 12 15:16:26 2013 +0100 @@ -424,21 +424,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 Mon Apr 08 21:17:57 2013 +0100 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Wed Jun 12 15:16:26 2013 +0100 @@ -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; @@ -34,8 +33,11 @@ import java.util.ArrayList; import java.util.Arrays; import sun.reflect.Reflection; +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 @@ -583,9 +585,8 @@ public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - return accessStatic(refc, method, callerClass); + checkSecurityManager(refc, method); + return accessStatic(refc, method, findBoundCallerClass(method)); } private MethodHandle accessStatic(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { @@ -640,9 +641,8 @@ */ public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - return accessVirtual(refc, 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); @@ -651,7 +651,7 @@ private MethodHandle accessVirtual(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException { checkMethod(refc, method, false); MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - mh = maybeBindCaller(method, mh, callerClass); + mh = maybeBindCaller(method, mh, findBoundCallerClass(method)); return restrictProtectedReceiver(method, mh); } @@ -684,7 +684,7 @@ 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); // stack walk magic: do not refactor + checkSecurityManager(refc, ctor); return accessConstructor(refc, ctor); } private MethodHandle accessConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException { @@ -754,9 +754,8 @@ Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSpecialCaller(specialCaller); MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - return accessSpecial(refc, method, callerClass, specialCaller); + checkSecurityManager(refc, method); + return accessSpecial(refc, method, findBoundCallerClass(method), specialCaller); } private MethodHandle accessSpecial(Class<?> refc, MemberName method, Class<?> callerClass, @@ -815,7 +814,7 @@ */ public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field); return makeAccessor(refc, field, false, false, 0); } private MethodHandle resolveGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { @@ -842,7 +841,7 @@ */ public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(refc, name, type, false); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field); return makeAccessor(refc, field, false, true, 0); } private MethodHandle resolveSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { @@ -868,7 +867,7 @@ */ public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field); return makeAccessor(refc, field, false, false, 1); } private MethodHandle resolveStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { @@ -894,7 +893,7 @@ */ public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(refc, name, type, true); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field); return makeAccessor(refc, field, false, true, 1); } private MethodHandle resolveStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { @@ -951,11 +950,10 @@ 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); - checkSecurityManager(refc, method); // stack walk magic: do not refactor + checkSecurityManager(refc, method); checkMethod(refc, method, false); MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); - Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - MethodHandle bcmh = maybeBindCaller(method, dmh, 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) @@ -1023,8 +1021,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 = findBoundCallerClass(method); // stack walk magic: do not refactor - mh = maybeBindCaller(method, mh, callerClass); + mh = maybeBindCaller(method, mh, findBoundCallerClass(method)); return restrictReceiver(method, mh, specialCaller); } @@ -1131,22 +1128,43 @@ /** * 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. * This is the same caller class as is used by checkSecurityManager. * This function performs stack walk magic: do not refactor it. */ - Class<?> findBoundCallerClass(MemberName m) { + 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: - : getCallerClassAtEntryPoint(true)); + // 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. + */ + private boolean isCheckMemberAccessOverridden(SecurityManager sm) { + final Class<? extends SecurityManager> cls = sm.getClass(); + if (cls == SecurityManager.class) return false; + + try { + return cls.getMethod("checkMemberAccess", Class.class, int.class). + getDeclaringClass() != SecurityManager.class; + } catch (NoSuchMethodException e) { + throw new InternalError("should not reach here"); + } + } + /** * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. * Determines a trustable caller class to compare with refc, the symbolic reference class. @@ -1158,24 +1176,32 @@ SecurityManager smgr = System.getSecurityManager(); if (smgr == null) return; if (allowedModes == TRUSTED) return; + + final boolean overridden = isCheckMemberAccessOverridden(smgr); // 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)); + if (!isFullPowerLookup() || + !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) { + ReflectUtil.checkPackageAccess(refc); + } // Step 3: if (m.isPublic()) return; Class<?> defc = m.getDeclaringClass(); - smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE + if (!overridden) { + if (!isFullPowerLookup() || + (lookupClass.getClassLoader() != defc.getClassLoader())) { + smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + } + } else { + // Don't refactor; otherwise break the stack depth for + // checkMemberAccess of subclasses of SecurityManager as specified. + smgr.checkMemberAccess(defc, Member.DECLARED); + } // Step 4: - if (defc != refc) - smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); + if (defc != refc) { + ReflectUtil.checkPackageAccess(defc); + } // Comment from SM.checkMemberAccess, where which=DECLARED: /*