提交 56dfa24d 编写于 作者: M mchung

8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive

Reviewed-by: jrose, alanb, twisti
上级 549df33b
...@@ -48,7 +48,6 @@ FILES_c = \ ...@@ -48,7 +48,6 @@ FILES_c = \
Proxy.c \ Proxy.c \
RandomAccessFile.c \ RandomAccessFile.c \
RandomAccessFile_md.c \ RandomAccessFile_md.c \
ResourceBundle.c \
Runtime.c \ Runtime.c \
SecurityManager.c \ SecurityManager.c \
Shutdown.c \ Shutdown.c \
......
...@@ -134,7 +134,6 @@ SUNWprivate_1.1 { ...@@ -134,7 +134,6 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_longBitsToDouble;
...@@ -233,7 +232,6 @@ SUNWprivate_1.1 { ...@@ -233,7 +232,6 @@ SUNWprivate_1.1 {
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext;
Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
......
...@@ -73,7 +73,6 @@ text: .text%writeBytes; ...@@ -73,7 +73,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -78,7 +78,6 @@ text: .text%writeBytes; ...@@ -78,7 +78,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -74,7 +74,6 @@ text: .text%writeBytes; ...@@ -74,7 +74,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -134,7 +134,6 @@ SUNWprivate_1.1 { ...@@ -134,7 +134,6 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_longBitsToDouble;
...@@ -233,7 +232,6 @@ SUNWprivate_1.1 { ...@@ -233,7 +232,6 @@ SUNWprivate_1.1 {
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext;
Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
......
...@@ -78,7 +78,6 @@ text: .text%writeBytes; ...@@ -78,7 +78,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -74,7 +74,6 @@ text: .text%writeBytes; ...@@ -74,7 +74,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -73,7 +73,6 @@ text: .text%writeBytes; ...@@ -73,7 +73,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -53,6 +53,7 @@ import java.util.Map; ...@@ -53,6 +53,7 @@ import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool; import sun.reflect.ConstantPool;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
...@@ -250,9 +251,11 @@ public final class Class<T> implements java.io.Serializable, ...@@ -250,9 +251,11 @@ public final class Class<T> implements java.io.Serializable,
* by this method fails * by this method fails
* @exception ClassNotFoundException if the class cannot be located * @exception ClassNotFoundException if the class cannot be located
*/ */
@CallerSensitive
public static Class<?> forName(String className) public static Class<?> forName(String className)
throws ClassNotFoundException { throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader()); return forName0(className, true,
ClassLoader.getClassLoader(Reflection.getCallerClass()));
} }
...@@ -317,6 +320,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -317,6 +320,7 @@ public final class Class<T> implements java.io.Serializable,
* @see java.lang.ClassLoader * @see java.lang.ClassLoader
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public static Class<?> forName(String name, boolean initialize, public static Class<?> forName(String name, boolean initialize,
ClassLoader loader) ClassLoader loader)
throws ClassNotFoundException throws ClassNotFoundException
...@@ -324,7 +328,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -324,7 +328,7 @@ public final class Class<T> implements java.io.Serializable,
if (sun.misc.VM.isSystemDomainLoader(loader)) { if (sun.misc.VM.isSystemDomainLoader(loader)) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (!sun.misc.VM.isSystemDomainLoader(ccl)) { if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission( sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION); SecurityConstants.GET_CLASSLOADER_PERMISSION);
...@@ -386,18 +390,14 @@ public final class Class<T> implements java.io.Serializable, ...@@ -386,18 +390,14 @@ public final class Class<T> implements java.io.Serializable,
* </ul> * </ul>
* *
*/ */
@CallerSensitive
public T newInstance() public T newInstance()
throws InstantiationException, IllegalAccessException throws InstantiationException, IllegalAccessException
{ {
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
} }
return newInstance0();
}
private T newInstance0()
throws InstantiationException, IllegalAccessException
{
// NOTE: the following code may not be strictly correct under // NOTE: the following code may not be strictly correct under
// the current Java memory model. // the current Java memory model.
...@@ -432,7 +432,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -432,7 +432,7 @@ public final class Class<T> implements java.io.Serializable,
// Security check (same as in java.lang.reflect.Constructor) // Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers(); int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) { if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass(3); Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) { if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers); Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller; newInstanceCallerCache = caller;
...@@ -674,16 +674,14 @@ public final class Class<T> implements java.io.Serializable, ...@@ -674,16 +674,14 @@ public final class Class<T> implements java.io.Serializable,
* @see SecurityManager#checkPermission * @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission * @see java.lang.RuntimePermission
*/ */
@CallerSensitive
public ClassLoader getClassLoader() { public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0(); ClassLoader cl = getClassLoader0();
if (cl == null) if (cl == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return cl; return cl;
} }
...@@ -1392,11 +1390,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1392,11 +1390,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Class<?>[] getClasses() { public Class<?>[] getClasses() {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
// Privileged so this implementation can look at DECLARED classes, // Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here // something the caller might not have privilege to do. The code here
...@@ -1467,11 +1463,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1467,11 +1463,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field[] getFields() throws SecurityException { public Field[] getFields() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetPublicFields(null)); return copyFields(privateGetPublicFields(null));
} }
...@@ -1518,11 +1512,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1518,11 +1512,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method[] getMethods() throws SecurityException { public Method[] getMethods() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetPublicMethods()); return copyMethods(privateGetPublicMethods());
} }
...@@ -1567,11 +1559,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1567,11 +1559,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException { public Constructor<?>[] getConstructors() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(true)); return copyConstructors(privateGetDeclaredConstructors(true));
} }
...@@ -1625,12 +1615,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1625,12 +1615,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field getField(String name) public Field getField(String name)
throws NoSuchFieldException, SecurityException { throws NoSuchFieldException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Field field = getField0(name); Field field = getField0(name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -1710,12 +1698,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1710,12 +1698,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes) public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Method method = getMethod0(name, parameterTypes); Method method = getMethod0(name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -1764,12 +1750,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1764,12 +1750,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes) public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.PUBLIC); return getConstructor0(parameterTypes, Member.PUBLIC);
} }
...@@ -1807,11 +1791,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1807,11 +1791,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException { public Class<?>[] getDeclaredClasses() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
return getDeclaredClasses0(); return getDeclaredClasses0();
} }
...@@ -1851,11 +1833,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1851,11 +1833,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException { public Field[] getDeclaredFields() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetDeclaredFields(false)); return copyFields(privateGetDeclaredFields(false));
} }
...@@ -1899,11 +1879,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1899,11 +1879,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException { public Method[] getDeclaredMethods() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetDeclaredMethods(false)); return copyMethods(privateGetDeclaredMethods(false));
} }
...@@ -1944,11 +1922,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1944,11 +1922,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException { public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(false)); return copyConstructors(privateGetDeclaredConstructors(false));
} }
...@@ -1987,12 +1963,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1987,12 +1963,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field getDeclaredField(String name) public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException { throws NoSuchFieldException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Field field = searchFields(privateGetDeclaredFields(false), name); Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -2042,12 +2016,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2042,12 +2016,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -2092,12 +2064,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2092,12 +2064,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.DECLARED); return getConstructor0(parameterTypes, Member.DECLARED);
} }
...@@ -2255,23 +2225,40 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2255,23 +2225,40 @@ public final class Class<T> implements java.io.Serializable,
*/ */
static native Class<?> getPrimitiveClass(String name); static native Class<?> getPrimitiveClass(String name);
private static boolean isCheckMemberAccessOverridden(SecurityManager smgr) {
if (smgr.getClass() == SecurityManager.class) return false;
Class<?>[] paramTypes = new Class<?>[] {Class.class, int.class};
return smgr.getClass().getMethod0("checkMemberAccess", paramTypes).
getDeclaringClass() != SecurityManager.class;
}
/* /*
* Check if client is allowed to access members. If access is denied, * Check if client is allowed to access members. If access is denied,
* throw a SecurityException. * throw a SecurityException.
* *
* Be very careful not to change the stack depth of this checkMemberAccess
* call for security reasons.
* See java.lang.SecurityManager.checkMemberAccess.
*
* <p> Default policy: allow all clients access with normal Java access * <p> Default policy: allow all clients access with normal Java access
* control. * control.
*/ */
private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
SecurityManager s = System.getSecurityManager(); final SecurityManager s = System.getSecurityManager();
if (s != null) { if (s != null) {
s.checkMemberAccess(this, which); final ClassLoader ccl = ClassLoader.getClassLoader(caller);
ClassLoader cl = getClassLoader0(); final ClassLoader cl = getClassLoader0();
if (!isCheckMemberAccessOverridden(s)) {
// Inlined SecurityManager.checkMemberAccess
if (which != Member.PUBLIC) {
if (ccl != cl) {
s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
}
} else {
// Don't refactor; otherwise break the stack depth for
// checkMemberAccess of subclasses of SecurityManager as specified.
s.checkMemberAccess(this, which);
}
if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName(); String name = this.getName();
int i = name.lastIndexOf('.'); int i = name.lastIndexOf('.');
......
...@@ -55,6 +55,7 @@ import sun.misc.CompoundEnumeration; ...@@ -55,6 +55,7 @@ import sun.misc.CompoundEnumeration;
import sun.misc.Resource; import sun.misc.Resource;
import sun.misc.URLClassPath; import sun.misc.URLClassPath;
import sun.misc.VM; import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -1159,11 +1160,6 @@ public abstract class ClassLoader { ...@@ -1159,11 +1160,6 @@ public abstract class ClassLoader {
return java.util.Collections.emptyEnumeration(); return java.util.Collections.emptyEnumeration();
} }
// index 0: java.lang.ClassLoader.class
// index 1: the immediate caller of index 0.
// index 2: the immediate caller of index 1.
private static native Class<? extends ClassLoader> getCaller(int index);
/** /**
* Registers the caller as parallel capable.</p> * Registers the caller as parallel capable.</p>
* The registration succeeds if and only if all of the following * The registration succeeds if and only if all of the following
...@@ -1179,8 +1175,11 @@ public abstract class ClassLoader { ...@@ -1179,8 +1175,11 @@ public abstract class ClassLoader {
* *
* @since 1.7 * @since 1.7
*/ */
@CallerSensitive
protected static boolean registerAsParallelCapable() { protected static boolean registerAsParallelCapable() {
return ParallelLoaders.register(getCaller(1)); Class<? extends ClassLoader> callerClass =
Reflection.getCallerClass().asSubclass(ClassLoader.class);
return ParallelLoaders.register(callerClass);
} }
/** /**
...@@ -1340,15 +1339,13 @@ public abstract class ClassLoader { ...@@ -1340,15 +1339,13 @@ public abstract class ClassLoader {
* *
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public final ClassLoader getParent() { public final ClassLoader getParent() {
if (parent == null) if (parent == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); checkClassLoaderPermission(this, Reflection.getCallerClass());
if (needsClassLoaderPermissionCheck(ccl, this)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return parent; return parent;
} }
...@@ -1408,6 +1405,7 @@ public abstract class ClassLoader { ...@@ -1408,6 +1405,7 @@ public abstract class ClassLoader {
* *
* @revised 1.4 * @revised 1.4
*/ */
@CallerSensitive
public static ClassLoader getSystemClassLoader() { public static ClassLoader getSystemClassLoader() {
initSystemClassLoader(); initSystemClassLoader();
if (scl == null) { if (scl == null) {
...@@ -1415,10 +1413,7 @@ public abstract class ClassLoader { ...@@ -1415,10 +1413,7 @@ public abstract class ClassLoader {
} }
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); checkClassLoaderPermission(scl, Reflection.getCallerClass());
if (needsClassLoaderPermissionCheck(ccl, scl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return scl; return scl;
} }
...@@ -1471,8 +1466,8 @@ public abstract class ClassLoader { ...@@ -1471,8 +1466,8 @@ public abstract class ClassLoader {
// class loader 'from' is same as class loader 'to' or an ancestor // class loader 'from' is same as class loader 'to' or an ancestor
// of 'to'. The class loader in a system domain can access // of 'to'. The class loader in a system domain can access
// any class loader. // any class loader.
static boolean needsClassLoaderPermissionCheck(ClassLoader from, private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
ClassLoader to) ClassLoader to)
{ {
if (from == to) if (from == to)
return false; return false;
...@@ -1483,13 +1478,8 @@ public abstract class ClassLoader { ...@@ -1483,13 +1478,8 @@ public abstract class ClassLoader {
return !to.isAncestor(from); return !to.isAncestor(from);
} }
// Returns the invoker's class loader, or null if none. // Returns the class's class loader, or null if none.
// NOTE: This must always be invoked when there is exactly one intervening static ClassLoader getClassLoader(Class<?> caller) {
// frame from the core libraries on the stack between this method's
// invocation and the desired invoker.
static ClassLoader getCallerClassLoader() {
// NOTE use of more generic Reflection.getCallerClass()
Class<?> caller = Reflection.getCallerClass(3);
// This can be null if the VM is requesting it // This can be null if the VM is requesting it
if (caller == null) { if (caller == null) {
return null; return null;
...@@ -1498,6 +1488,17 @@ public abstract class ClassLoader { ...@@ -1498,6 +1488,17 @@ public abstract class ClassLoader {
return caller.getClassLoader0(); return caller.getClassLoader0();
} }
static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// caller can be null if the VM is requesting it
ClassLoader ccl = getClassLoader(caller);
if (needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
// The class loader for the system // The class loader for the system
// @GuardedBy("ClassLoader.class") // @GuardedBy("ClassLoader.class")
private static ClassLoader scl; private static ClassLoader scl;
......
...@@ -49,6 +49,8 @@ import java.util.HashMap; ...@@ -49,6 +49,8 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import sun.net.www.ParseUtil; import sun.net.www.ParseUtil;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
...@@ -273,8 +275,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { ...@@ -273,8 +275,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
* @return the package of the requested name. It may be null if no package * @return the package of the requested name. It may be null if no package
* information is available from the archive or codebase. * information is available from the archive or codebase.
*/ */
@CallerSensitive
public static Package getPackage(String name) { public static Package getPackage(String name) {
ClassLoader l = ClassLoader.getCallerClassLoader(); ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) { if (l != null) {
return l.getPackage(name); return l.getPackage(name);
} else { } else {
...@@ -294,8 +297,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { ...@@ -294,8 +297,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
* @return a new array of packages known to the callers {@code ClassLoader} * @return a new array of packages known to the callers {@code ClassLoader}
* instance. An zero length array is returned if none are known. * instance. An zero length array is returned if none are known.
*/ */
@CallerSensitive
public static Package[] getPackages() { public static Package[] getPackages() {
ClassLoader l = ClassLoader.getCallerClassLoader(); ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) { if (l != null) {
return l.getPackages(); return l.getPackages();
} else { } else {
......
...@@ -27,6 +27,8 @@ package java.lang; ...@@ -27,6 +27,8 @@ package java.lang;
import java.io.*; import java.io.*;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* Every Java application has a single instance of class * Every Java application has a single instance of class
...@@ -790,8 +792,9 @@ public class Runtime { ...@@ -790,8 +792,9 @@ public class Runtime {
* @see java.lang.SecurityException * @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public void load(String filename) { public void load(String filename) {
load0(System.getCallerClass(), filename); load0(Reflection.getCallerClass(), filename);
} }
synchronized void load0(Class<?> fromClass, String filename) { synchronized void load0(Class<?> fromClass, String filename) {
...@@ -850,8 +853,9 @@ public class Runtime { ...@@ -850,8 +853,9 @@ public class Runtime {
* @see java.lang.SecurityException * @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public void loadLibrary(String libname) { public void loadLibrary(String libname) {
loadLibrary0(System.getCallerClass(), libname); loadLibrary0(Reflection.getCallerClass(), libname);
} }
synchronized void loadLibrary0(Class<?> fromClass, String libname) { synchronized void loadLibrary0(Class<?> fromClass, String libname) {
......
...@@ -36,10 +36,10 @@ import java.net.SocketPermission; ...@@ -36,10 +36,10 @@ import java.net.SocketPermission;
import java.net.NetPermission; import java.net.NetPermission;
import java.util.Hashtable; import java.util.Hashtable;
import java.net.InetAddress; import java.net.InetAddress;
import java.lang.reflect.Member;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.URL; import java.net.URL;
import sun.reflect.CallerSensitive;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
/** /**
...@@ -1679,6 +1679,7 @@ class SecurityManager { ...@@ -1679,6 +1679,7 @@ class SecurityManager {
* @since JDK1.1 * @since JDK1.1
* @see #checkPermission(java.security.Permission) checkPermission * @see #checkPermission(java.security.Permission) checkPermission
*/ */
@CallerSensitive
public void checkMemberAccess(Class<?> clazz, int which) { public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == null) { if (clazz == null) {
throw new NullPointerException("class can't be null"); throw new NullPointerException("class can't be null");
......
...@@ -35,6 +35,7 @@ import java.security.AllPermission; ...@@ -35,6 +35,7 @@ import java.security.AllPermission;
import java.nio.channels.Channel; import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
import sun.nio.ch.Interruptible; import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import sun.reflect.annotation.AnnotationType; import sun.reflect.annotation.AnnotationType;
...@@ -1072,8 +1073,9 @@ public final class System { ...@@ -1072,8 +1073,9 @@ public final class System {
* @see java.lang.Runtime#load(java.lang.String) * @see java.lang.Runtime#load(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public static void load(String filename) { public static void load(String filename) {
Runtime.getRuntime().load0(getCallerClass(), filename); Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
} }
/** /**
...@@ -1107,8 +1109,9 @@ public final class System { ...@@ -1107,8 +1109,9 @@ public final class System {
* @see java.lang.Runtime#loadLibrary(java.lang.String) * @see java.lang.Runtime#loadLibrary(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public static void loadLibrary(String libname) { public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname); Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
} }
/** /**
...@@ -1245,10 +1248,4 @@ public final class System { ...@@ -1245,10 +1248,4 @@ public final class System {
} }
}); });
} }
/* returns the class of the caller. */
static Class<?> getCallerClass() {
// NOTE use of more generic Reflection.getCallerClass()
return Reflection.getCallerClass(3);
}
} }
...@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible; import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -1443,15 +1445,14 @@ class Thread implements Runnable { ...@@ -1443,15 +1445,14 @@ class Thread implements Runnable {
* *
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public ClassLoader getContextClassLoader() { public ClassLoader getContextClassLoader() {
if (contextClassLoader == null) if (contextClassLoader == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader.checkClassLoaderPermission(contextClassLoader,
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) { Reflection.getCallerClass());
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return contextClassLoader; return contextClassLoader;
} }
......
...@@ -709,7 +709,9 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -709,7 +709,9 @@ import jdk.internal.org.objectweb.asm.Type;
InvokerBytecodeGenerator.maybeDump(className, classFile); InvokerBytecodeGenerator.maybeDump(className, classFile);
Class<? extends BoundMethodHandle> bmhClass = Class<? extends BoundMethodHandle> bmhClass =
//UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class);
UNSAFE.defineClass(className, classFile, 0, classFile.length).asSubclass(BoundMethodHandle.class); UNSAFE.defineClass(className, classFile, 0, classFile.length,
BoundMethodHandle.class.getClassLoader(), null)
.asSubclass(BoundMethodHandle.class);
UNSAFE.ensureClassInitialized(bmhClass); UNSAFE.ensureClassInitialized(bmhClass);
return bmhClass; return bmhClass;
......
...@@ -391,10 +391,11 @@ import java.util.Objects; ...@@ -391,10 +391,11 @@ import java.util.Objects;
// private flags, not part of RECOGNIZED_MODIFIERS: // private flags, not part of RECOGNIZED_MODIFIERS:
static final int static final int
IS_METHOD = MN_IS_METHOD, // method (not constructor) IS_METHOD = MN_IS_METHOD, // method (not constructor)
IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
IS_FIELD = MN_IS_FIELD, // field IS_FIELD = MN_IS_FIELD, // field
IS_TYPE = MN_IS_TYPE; // nested type IS_TYPE = MN_IS_TYPE, // nested type
CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
...@@ -430,6 +431,10 @@ import java.util.Objects; ...@@ -430,6 +431,10 @@ import java.util.Objects;
public boolean isPackage() { public boolean isPackage() {
return !testAnyFlags(ALL_ACCESS); return !testAnyFlags(ALL_ACCESS);
} }
/** Query whether this member has a CallerSensitive annotation. */
public boolean isCallerSensitive() {
return testAllFlags(CALLER_SENSITIVE);
}
/** Utility method to query whether this member is accessible from a given lookup class. */ /** Utility method to query whether this member is accessible from a given lookup class. */
public boolean isAccessibleFrom(Class<?> lookupClass) { public boolean isAccessibleFrom(Class<?> lookupClass) {
......
...@@ -34,6 +34,8 @@ import sun.invoke.empty.Empty; ...@@ -34,6 +34,8 @@ import sun.invoke.empty.Empty;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType; import sun.invoke.util.VerifyType;
import sun.invoke.util.Wrapper; import sun.invoke.util.Wrapper;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
...@@ -891,9 +893,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -891,9 +893,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
} }
@CallerSensitive
private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) { private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected // This method is called via MH_checkCallerClass and so it's
Class<?> actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG); // correct to ask for the immediate caller here.
Class<?> actual = Reflection.getCallerClass();
if (actual != expected && actual != expected2) if (actual != expected && actual != expected2)
throw new InternalError("found "+actual.getName()+", expected "+expected.getName() throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
+(expected == expected2 ? "" : ", or else "+expected2.getName())); +(expected == expected2 ? "" : ", or else "+expected2.getName()));
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
package java.lang.invoke; package java.lang.invoke;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
...@@ -34,7 +33,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -34,7 +33,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/** /**
* The JVM interface for the method handles package is all here. * The JVM interface for the method handles package is all here.
* This is an interface internal and private to an implemetantion of JSR 292. * This is an interface internal and private to an implementation of JSR 292.
* <em>This class is not part of the JSR 292 standard.</em> * <em>This class is not part of the JSR 292 standard.</em>
* @author jrose * @author jrose
*/ */
...@@ -101,6 +100,7 @@ class MethodHandleNatives { ...@@ -101,6 +100,7 @@ class MethodHandleNatives {
MN_IS_CONSTRUCTOR = 0x00020000, // constructor MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_REFERENCE_KIND_SHIFT = 24, // refKind MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers: // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
...@@ -391,129 +391,24 @@ class MethodHandleNatives { ...@@ -391,129 +391,24 @@ class MethodHandleNatives {
* I.e., does it call Reflection.getCallerClass or a similer method * I.e., does it call Reflection.getCallerClass or a similer method
* to ask about the identity of its caller? * to ask about the identity of its caller?
*/ */
// FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive.
static boolean isCallerSensitive(MemberName mem) { static boolean isCallerSensitive(MemberName mem) {
if (!mem.isInvocable()) return false; // fields are not caller sensitive if (!mem.isInvocable()) return false; // fields are not caller sensitive
return mem.isCallerSensitive() || canBeCalledVirtual(mem);
}
static boolean canBeCalledVirtual(MemberName mem) {
assert(mem.isInvocable());
Class<?> defc = mem.getDeclaringClass(); Class<?> defc = mem.getDeclaringClass();
switch (mem.getName()) { switch (mem.getName()) {
case "doPrivileged":
case "doPrivilegedWithCombiner":
return defc == java.security.AccessController.class;
case "checkMemberAccess": case "checkMemberAccess":
return canBeCalledVirtual(mem, java.lang.SecurityManager.class); return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
case "getUnsafe":
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":
case "getBoolean":
case "getByte":
case "getChar":
case "getShort":
case "getInt":
case "getLong":
case "getFloat":
case "getDouble":
case "set":
case "setBoolean":
case "setByte":
case "setChar":
case "setShort":
case "setInt":
case "setLong":
case "setFloat":
case "setDouble":
return defc == java.lang.reflect.Field.class;
case "newInstance":
if (defc == java.lang.reflect.Constructor.class) return true;
if (defc == java.lang.Class.class) return true;
break;
case "forName":
case "getClassLoader":
case "getClasses":
case "getFields":
case "getMethods":
case "getConstructors":
case "getDeclaredClasses":
case "getDeclaredFields":
case "getDeclaredMethods":
case "getDeclaredConstructors":
case "getField":
case "getMethod":
case "getConstructor":
case "getDeclaredField":
case "getDeclaredMethod":
case "getDeclaredConstructor":
return defc == java.lang.Class.class;
case "getConnection":
case "getDriver":
case "getDrivers":
case "deregisterDriver":
return defc == getClass("java.sql.DriverManager");
case "newUpdater":
if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true;
if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true;
if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true;
break;
case "getContextClassLoader": case "getContextClassLoader":
return canBeCalledVirtual(mem, java.lang.Thread.class); return canBeCalledVirtual(mem, java.lang.Thread.class);
case "getPackage":
case "getPackages":
return defc == java.lang.Package.class;
case "getParent":
case "getSystemClassLoader":
return defc == java.lang.ClassLoader.class;
case "load":
case "loadLibrary":
if (defc == java.lang.Runtime.class) return true;
if (defc == java.lang.System.class) return true;
break;
case "getCallerClass":
if (defc == sun.reflect.Reflection.class) return true;
if (defc == java.lang.System.class) return true;
break;
case "getCallerClassLoader":
return defc == java.lang.ClassLoader.class;
case "registerAsParallelCapable":
return canBeCalledVirtual(mem, java.lang.ClassLoader.class);
case "getProxyClass":
case "newProxyInstance":
return defc == java.lang.reflect.Proxy.class;
case "asInterfaceInstance":
return defc == java.lang.invoke.MethodHandleProxies.class;
case "getBundle":
case "clearCache":
return defc == java.util.ResourceBundle.class;
} }
return false; return false;
} }
// avoid static dependency to a class in other modules
private static Class<?> getClass(String cn) {
try {
return Class.forName(cn, false,
MethodHandleNatives.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new InternalError(e);
}
}
static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) { static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
Class<?> symbolicRefClass = symbolicRef.getDeclaringClass(); Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
if (symbolicRefClass == definingClass) return true; if (symbolicRefClass == definingClass) return true;
......
...@@ -30,6 +30,7 @@ import java.security.AccessController; ...@@ -30,6 +30,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance; import sun.invoke.WrapperInstance;
import java.util.ArrayList; import java.util.ArrayList;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
...@@ -137,14 +138,14 @@ public class MethodHandleProxies { ...@@ -137,14 +138,14 @@ public class MethodHandleProxies {
// entry points, must be covered by hand-written or automatically // entry points, must be covered by hand-written or automatically
// generated adapter classes. // generated adapter classes.
// //
@CallerSensitive
public static public static
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) { <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
throw new IllegalArgumentException("not a public interface: "+intfc.getName()); throw new IllegalArgumentException("not a public interface: "+intfc.getName());
final MethodHandle mh; final MethodHandle mh;
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller final Class<?> caller = Reflection.getCallerClass();
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
ReflectUtil.checkProxyPackageAccess(ccl, intfc); ReflectUtil.checkProxyPackageAccess(ccl, intfc);
mh = ccl != null ? bindCaller(target, caller) : target; mh = ccl != null ? bindCaller(target, caller) : target;
......
...@@ -26,13 +26,17 @@ ...@@ -26,13 +26,17 @@
package java.lang.invoke; package java.lang.invoke;
import java.lang.reflect.*; import java.lang.reflect.*;
import sun.invoke.util.ValueConversions; import java.security.AccessController;
import sun.invoke.util.VerifyAccess; import java.security.PrivilegedAction;
import sun.invoke.util.Wrapper;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyAccess;
import sun.invoke.util.Wrapper;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleNatives.Constants.*;
...@@ -65,8 +69,9 @@ public class MethodHandles { ...@@ -65,8 +69,9 @@ public class MethodHandles {
* This lookup object is a <em>capability</em> which may be delegated to trusted agents. * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
* Do not store it in place where untrusted code can access it. * Do not store it in place where untrusted code can access it.
*/ */
@CallerSensitive
public static Lookup lookup() { public static Lookup lookup() {
return new Lookup(); return new Lookup(Reflection.getCallerClass());
} }
/** /**
...@@ -416,18 +421,11 @@ public class MethodHandles { ...@@ -416,18 +421,11 @@ public class MethodHandles {
* for method handle creation. * for method handle creation.
* Must be called by from a method in this package, * Must be called by from a method in this package,
* which in turn is called by a method not in this package. * which in turn is called by a method not in this package.
* <p>
* Also, don't make it private, lest javac interpose
* an access$N method.
*/ */
Lookup() {
this(getCallerClassAtEntryPoint(false), ALL_MODES);
// make sure we haven't accidentally picked up a privileged class:
checkUnprivilegedlookupClass(lookupClass);
}
Lookup(Class<?> lookupClass) { Lookup(Class<?> lookupClass) {
this(lookupClass, ALL_MODES); this(lookupClass, ALL_MODES);
// make sure we haven't accidentally picked up a privileged class:
checkUnprivilegedlookupClass(lookupClass);
} }
private Lookup(Class<?> lookupClass, int allowedModes) { private Lookup(Class<?> lookupClass, int allowedModes) {
...@@ -554,20 +552,6 @@ public class MethodHandles { ...@@ -554,20 +552,6 @@ public class MethodHandles {
} }
} }
/* Obtain the external caller class, when called from Lookup.<init> or a first-level subroutine. */
private static Class<?> getCallerClassAtEntryPoint(boolean inSubroutine) {
final int CALLER_DEPTH = 4;
// Stack for the constructor entry point (inSubroutine=false):
// 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
// 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
// The stack is slightly different for a subroutine of a Lookup.find* method:
// 2: Lookup.*, 3: Lookup.find*.*, 4: caller
// Note: This should be the only use of getCallerClass in this file.
assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class);
assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class));
return Reflection.getCallerClass(CALLER_DEPTH);
}
/** /**
* Produces a method handle for a static method. * Produces a method handle for a static method.
* The type of the method handle will be that of the method. * The type of the method handle will be that of the method.
...@@ -594,12 +578,14 @@ public class MethodHandles { ...@@ -594,12 +578,14 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public public
MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
checkSecurityManager(refc, method); // stack walk magic: do not refactor Class<?> callerClass = Reflection.getCallerClass();
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor checkSecurityManager(refc, method, callerClass);
return getDirectMethod(REF_invokeStatic, refc, method, callerClass); return getDirectMethod(REF_invokeStatic, refc, method,
findBoundCallerClass(method, callerClass));
} }
/** /**
...@@ -645,6 +631,7 @@ public class MethodHandles { ...@@ -645,6 +631,7 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
if (refc == MethodHandle.class) { if (refc == MethodHandle.class) {
MethodHandle mh = findVirtualForMH(name, type); MethodHandle mh = findVirtualForMH(name, type);
...@@ -652,9 +639,10 @@ public class MethodHandles { ...@@ -652,9 +639,10 @@ public class MethodHandles {
} }
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
MemberName method = resolveOrFail(refKind, refc, name, type); MemberName method = resolveOrFail(refKind, refc, name, type);
checkSecurityManager(refc, method); // stack walk magic: do not refactor Class<?> callerClass = Reflection.getCallerClass();
Class<?> callerClass = findBoundCallerClass(method); checkSecurityManager(refc, method, callerClass);
return getDirectMethod(refKind, refc, method, callerClass); return getDirectMethod(refKind, refc, method,
findBoundCallerClass(method, callerClass));
} }
private MethodHandle findVirtualForMH(String name, MethodType type) { private MethodHandle findVirtualForMH(String name, MethodType type) {
// these names require special lookups because of the implicit MethodType argument // these names require special lookups because of the implicit MethodType argument
...@@ -691,10 +679,11 @@ public class MethodHandles { ...@@ -691,10 +679,11 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
String name = "<init>"; String name = "<init>";
MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
checkSecurityManager(refc, ctor); // stack walk magic: do not refactor checkSecurityManager(refc, ctor, Reflection.getCallerClass());
return getDirectConstructor(refc, ctor); return getDirectConstructor(refc, ctor);
} }
...@@ -732,14 +721,16 @@ public class MethodHandles { ...@@ -732,14 +721,16 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
checkSpecialCaller(specialCaller); checkSpecialCaller(specialCaller);
Lookup specialLookup = this.in(specialCaller); Lookup specialLookup = this.in(specialCaller);
MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
checkSecurityManager(refc, method); // stack walk magic: do not refactor Class<?> callerClass = Reflection.getCallerClass();
Class<?> callerClass = findBoundCallerClass(method); checkSecurityManager(refc, method, callerClass);
return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method,
findBoundCallerClass(method, callerClass));
} }
/** /**
...@@ -759,9 +750,10 @@ public class MethodHandles { ...@@ -759,9 +750,10 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_getField, refc, name, type); MemberName field = resolveOrFail(REF_getField, refc, name, type);
checkSecurityManager(refc, field); // stack walk magic: do not refactor checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_getField, refc, field); return getDirectField(REF_getField, refc, field);
} }
...@@ -782,9 +774,10 @@ public class MethodHandles { ...@@ -782,9 +774,10 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_putField, refc, name, type); MemberName field = resolveOrFail(REF_putField, refc, name, type);
checkSecurityManager(refc, field); // stack walk magic: do not refactor checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_putField, refc, field); return getDirectField(REF_putField, refc, field);
} }
...@@ -804,9 +797,10 @@ public class MethodHandles { ...@@ -804,9 +797,10 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_getStatic, refc, name, type); MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
checkSecurityManager(refc, field); // stack walk magic: do not refactor checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_getStatic, refc, field); return getDirectField(REF_getStatic, refc, field);
} }
...@@ -826,9 +820,10 @@ public class MethodHandles { ...@@ -826,9 +820,10 @@ public class MethodHandles {
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_putStatic, refc, name, type); MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
checkSecurityManager(refc, field); // stack walk magic: do not refactor checkSecurityManager(refc, field, Reflection.getCallerClass());
return getDirectField(REF_putStatic, refc, field); return getDirectField(REF_putStatic, refc, field);
} }
...@@ -878,12 +873,14 @@ return mh1; ...@@ -878,12 +873,14 @@ return mh1;
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a> * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
Class<? extends Object> refc = receiver.getClass(); // may get NPE Class<? extends Object> refc = receiver.getClass(); // may get NPE
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
checkSecurityManager(refc, method); // stack walk magic: do not refactor Class<?> callerClass = Reflection.getCallerClass();
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor checkSecurityManager(refc, method, callerClass);
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method,
findBoundCallerClass(method, callerClass));
return mh.bindReceiver(receiver).setVarargs(method); return mh.bindReceiver(receiver).setVarargs(method);
} }
...@@ -908,13 +905,14 @@ return mh1; ...@@ -908,13 +905,14 @@ return mh1;
* is set and {@code asVarargsCollector} fails * is set and {@code asVarargsCollector} fails
* @throws NullPointerException if the argument is null * @throws NullPointerException if the argument is null
*/ */
@CallerSensitive
public MethodHandle unreflect(Method m) throws IllegalAccessException { public MethodHandle unreflect(Method m) throws IllegalAccessException {
MemberName method = new MemberName(m); MemberName method = new MemberName(m);
byte refKind = method.getReferenceKind(); byte refKind = method.getReferenceKind();
if (refKind == REF_invokeSpecial) if (refKind == REF_invokeSpecial)
refKind = REF_invokeVirtual; refKind = REF_invokeVirtual;
assert(method.isMethod()); assert(method.isMethod());
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass());
Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass);
} }
...@@ -940,12 +938,13 @@ return mh1; ...@@ -940,12 +938,13 @@ return mh1;
* is set and {@code asVarargsCollector} fails * is set and {@code asVarargsCollector} fails
* @throws NullPointerException if any argument is null * @throws NullPointerException if any argument is null
*/ */
@CallerSensitive
public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException { public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
checkSpecialCaller(specialCaller); checkSpecialCaller(specialCaller);
Lookup specialLookup = this.in(specialCaller); Lookup specialLookup = this.in(specialCaller);
MemberName method = new MemberName(m, true); MemberName method = new MemberName(m, true);
assert(method.isMethod()); assert(method.isMethod());
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor Class<?> callerClass = findBoundCallerClass(method, Reflection.getCallerClass());
// ignore m.isAccessible: this is a new kind of access // ignore m.isAccessible: this is a new kind of access
return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass);
} }
...@@ -1050,20 +1049,35 @@ return mh1; ...@@ -1050,20 +1049,35 @@ return mh1;
* If this lookup object has private access, then the caller class is the lookupClass. * 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, it is the caller of the currently executing public API method (e.g., findVirtual).
* This is the same caller class as is used by checkSecurityManager. * 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, Class<?> callerAtEntryPoint) {
Class<?> callerClass = null; Class<?> callerClass = null;
if (MethodHandleNatives.isCallerSensitive(m)) { if (MethodHandleNatives.isCallerSensitive(m)) {
// Do not refactor this to a more "logical" place, since it is stack walk magic. // 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. // Note that this is the same expression as in Step 2 below in checkSecurityManager.
callerClass = ((allowedModes & PRIVATE) != 0 callerClass = ((allowedModes & PRIVATE) != 0
? lookupClass // for strong access modes, no extra check ? lookupClass // for strong access modes, no extra check
// next line does stack walk magic; do not refactor: : callerAtEntryPoint);
: getCallerClassAtEntryPoint(true));
} }
return callerClass; return callerClass;
} }
/**
* 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>. * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
* Determines a trustable caller class to compare with refc, the symbolic reference class. * Determines a trustable caller class to compare with refc, the symbolic reference class.
...@@ -1071,46 +1085,55 @@ return mh1; ...@@ -1071,46 +1085,55 @@ return mh1;
* Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual).
* This function performs stack walk magic: do not refactor it. * This function performs stack walk magic: do not refactor it.
*/ */
void checkSecurityManager(Class<?> refc, MemberName m) { void checkSecurityManager(Class<?> refc, MemberName m, Class<?> caller) {
SecurityManager smgr = System.getSecurityManager(); SecurityManager smgr = System.getSecurityManager();
if (smgr == null) return; if (smgr == null) return;
if (allowedModes == TRUSTED) return; if (allowedModes == TRUSTED) return;
final boolean overridden = isCheckMemberAccessOverridden(smgr);
// Step 1: // Step 1:
smgr.checkMemberAccess(refc, Member.PUBLIC); {
// Default policy is to allow Member.PUBLIC; no need to check
// permission if SecurityManager is the default implementation
final int which = Member.PUBLIC;
final Class<?> clazz = refc;
if (overridden) {
// Don't refactor; otherwise break the stack depth for
// checkMemberAccess of subclasses of SecurityManager as specified.
smgr.checkMemberAccess(clazz, which);
}
}
// Step 2: // Step 2:
Class<?> callerClass = ((allowedModes & PRIVATE) != 0 Class<?> callerClass = ((allowedModes & PRIVATE) != 0
? lookupClass // for strong access modes, no extra check ? lookupClass // for strong access modes, no extra check
// next line does stack walk magic; do not refactor: : caller);
: getCallerClassAtEntryPoint(true));
if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) ||
(callerClass != lookupClass && (callerClass != lookupClass &&
!VerifyAccess.classLoaderIsAncestor(callerClass, refc))) !VerifyAccess.classLoaderIsAncestor(callerClass, refc)))
smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); smgr.checkPackageAccess(VerifyAccess.getPackageName(refc));
// Step 3: // Step 3:
if (m.isPublic()) return; if (m.isPublic()) return;
Class<?> defc = m.getDeclaringClass(); Class<?> defc = m.getDeclaringClass();
smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE {
// Inline SecurityManager.checkMemberAccess
final int which = Member.DECLARED;
final Class<?> clazz = defc;
if (!overridden) {
if (caller.getClassLoader() != clazz.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(clazz, which);
}
}
// Step 4: // Step 4:
if (defc != refc) if (defc != refc)
smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); 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 { void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor; import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.repository.ConstructorRepository;
...@@ -392,14 +393,14 @@ public final class Constructor<T> extends Executable { ...@@ -392,14 +393,14 @@ public final class Constructor<T> extends Executable {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public T newInstance(Object ... initargs) public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException, throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException IllegalArgumentException, InvocationTargetException
{ {
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(2); Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers); checkAccess(caller, clazz, null, modifiers);
} }
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.FieldAccessor; import sun.reflect.FieldAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.FieldRepository; import sun.reflect.generics.repository.FieldRepository;
...@@ -376,9 +377,16 @@ class Field extends AccessibleObject implements Member { ...@@ -376,9 +377,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public Object get(Object obj) public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).get(obj); return getFieldAccessor(obj).get(obj);
} }
...@@ -404,9 +412,16 @@ class Field extends AccessibleObject implements Member { ...@@ -404,9 +412,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public boolean getBoolean(Object obj) public boolean getBoolean(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getBoolean(obj); return getFieldAccessor(obj).getBoolean(obj);
} }
...@@ -432,9 +447,16 @@ class Field extends AccessibleObject implements Member { ...@@ -432,9 +447,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public byte getByte(Object obj) public byte getByte(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getByte(obj); return getFieldAccessor(obj).getByte(obj);
} }
...@@ -462,9 +484,16 @@ class Field extends AccessibleObject implements Member { ...@@ -462,9 +484,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public char getChar(Object obj) public char getChar(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getChar(obj); return getFieldAccessor(obj).getChar(obj);
} }
...@@ -492,9 +521,16 @@ class Field extends AccessibleObject implements Member { ...@@ -492,9 +521,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public short getShort(Object obj) public short getShort(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getShort(obj); return getFieldAccessor(obj).getShort(obj);
} }
...@@ -522,9 +558,16 @@ class Field extends AccessibleObject implements Member { ...@@ -522,9 +558,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public int getInt(Object obj) public int getInt(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getInt(obj); return getFieldAccessor(obj).getInt(obj);
} }
...@@ -552,9 +595,16 @@ class Field extends AccessibleObject implements Member { ...@@ -552,9 +595,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public long getLong(Object obj) public long getLong(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getLong(obj); return getFieldAccessor(obj).getLong(obj);
} }
...@@ -582,9 +632,16 @@ class Field extends AccessibleObject implements Member { ...@@ -582,9 +632,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public float getFloat(Object obj) public float getFloat(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getFloat(obj); return getFieldAccessor(obj).getFloat(obj);
} }
...@@ -612,9 +669,16 @@ class Field extends AccessibleObject implements Member { ...@@ -612,9 +669,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public double getDouble(Object obj) public double getDouble(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getDouble(obj); return getFieldAccessor(obj).getDouble(obj);
} }
...@@ -684,9 +748,16 @@ class Field extends AccessibleObject implements Member { ...@@ -684,9 +748,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public void set(Object obj, Object value) public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).set(obj, value); getFieldAccessor(obj).set(obj, value);
} }
...@@ -714,9 +785,16 @@ class Field extends AccessibleObject implements Member { ...@@ -714,9 +785,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setBoolean(Object obj, boolean z) public void setBoolean(Object obj, boolean z)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setBoolean(obj, z); getFieldAccessor(obj).setBoolean(obj, z);
} }
...@@ -744,9 +822,16 @@ class Field extends AccessibleObject implements Member { ...@@ -744,9 +822,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setByte(Object obj, byte b) public void setByte(Object obj, byte b)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setByte(obj, b); getFieldAccessor(obj).setByte(obj, b);
} }
...@@ -774,9 +859,16 @@ class Field extends AccessibleObject implements Member { ...@@ -774,9 +859,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setChar(Object obj, char c) public void setChar(Object obj, char c)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setChar(obj, c); getFieldAccessor(obj).setChar(obj, c);
} }
...@@ -804,9 +896,16 @@ class Field extends AccessibleObject implements Member { ...@@ -804,9 +896,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setShort(Object obj, short s) public void setShort(Object obj, short s)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setShort(obj, s); getFieldAccessor(obj).setShort(obj, s);
} }
...@@ -834,9 +933,16 @@ class Field extends AccessibleObject implements Member { ...@@ -834,9 +933,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setInt(Object obj, int i) public void setInt(Object obj, int i)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setInt(obj, i); getFieldAccessor(obj).setInt(obj, i);
} }
...@@ -864,9 +970,16 @@ class Field extends AccessibleObject implements Member { ...@@ -864,9 +970,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setLong(Object obj, long l) public void setLong(Object obj, long l)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setLong(obj, l); getFieldAccessor(obj).setLong(obj, l);
} }
...@@ -894,9 +1007,16 @@ class Field extends AccessibleObject implements Member { ...@@ -894,9 +1007,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setFloat(Object obj, float f) public void setFloat(Object obj, float f)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setFloat(obj, f); getFieldAccessor(obj).setFloat(obj, f);
} }
...@@ -924,20 +1044,26 @@ class Field extends AccessibleObject implements Member { ...@@ -924,20 +1044,26 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setDouble(Object obj, double d) public void setDouble(Object obj, double d)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setDouble(obj, d); getFieldAccessor(obj).setDouble(obj, d);
} }
// Convenience routine which performs security checks // security check is done before calling this method
private FieldAccessor getFieldAccessor(Object obj) private FieldAccessor getFieldAccessor(Object obj)
throws IllegalAccessException throws IllegalAccessException
{ {
doSecurityCheck(obj);
boolean ov = override; boolean ov = override;
FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor; FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
return (a != null)? a : acquireFieldAccessor(ov); return (a != null) ? a : acquireFieldAccessor(ov);
} }
// NOTE that there is no synchronization used here. It is correct // NOTE that there is no synchronization used here. It is correct
...@@ -982,19 +1108,6 @@ class Field extends AccessibleObject implements Member { ...@@ -982,19 +1108,6 @@ class Field extends AccessibleObject implements Member {
} }
} }
// NOTE: be very careful if you change the stack depth of this
// routine. The depth of the "getCallerClass" call is hardwired so
// that the compiler can have an easier time if this gets inlined.
private void doSecurityCheck(Object obj) throws IllegalAccessException {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(4);
checkAccess(caller, clazz, obj, modifiers);
}
}
}
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.5 * @since 1.5
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.MethodAccessor; import sun.reflect.MethodAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.MethodRepository; import sun.reflect.generics.repository.MethodRepository;
...@@ -472,14 +473,14 @@ public final class Method extends Executable { ...@@ -472,14 +473,14 @@ public final class Method extends Executable {
* @exception ExceptionInInitializerError if the initialization * @exception ExceptionInInitializerError if the initialization
* provoked by this method fails. * provoked by this method fails.
*/ */
@CallerSensitive
public Object invoke(Object obj, Object... args) public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException, throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException InvocationTargetException
{ {
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(1); Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers); checkAccess(caller, clazz, obj, modifiers);
} }
} }
......
...@@ -39,6 +39,8 @@ import java.util.Set; ...@@ -39,6 +39,8 @@ import java.util.Set;
import java.util.List; import java.util.List;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.misc.ProxyGenerator; import sun.misc.ProxyGenerator;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -408,28 +410,21 @@ public class Proxy implements java.io.Serializable { ...@@ -408,28 +410,21 @@ public class Proxy implements java.io.Serializable {
* @throws NullPointerException if the {@code interfaces} array * @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null} * argument or any of its elements are {@code null}
*/ */
@CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader, public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces) Class<?>... interfaces)
throws IllegalArgumentException throws IllegalArgumentException
{
return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
}
private static void checkProxyLoader(ClassLoader ccl,
ClassLoader loader)
{ {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
if (loader == null && ccl != null) { checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
if (!ProxyAccessHelper.allowNullLoader) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
} }
return getProxyClass0(loader, interfaces);
} }
/* /*
* Generate a proxy class (caller-sensitive). * Check permissions required to create a Proxy class.
* *
* To define a proxy class, it performs the access checks as in * To define a proxy class, it performs the access checks as in
* Class.forName (VM will invoke ClassLoader.checkPackageAccess): * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
...@@ -446,17 +441,28 @@ public class Proxy implements java.io.Serializable { ...@@ -446,17 +441,28 @@ public class Proxy implements java.io.Serializable {
* will throw IllegalAccessError when the generated proxy class is * will throw IllegalAccessError when the generated proxy class is
* being defined via the defineClass0 method. * being defined via the defineClass0 method.
*/ */
private static Class<?> getProxyClass0(ClassLoader loader, private static void checkProxyAccess(Class<?> caller,
Class<?>... interfaces) { ClassLoader loader,
Class<?>... interfaces)
{
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller ClassLoader ccl = caller.getClassLoader();
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME); if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
final ClassLoader ccl = caller.getClassLoader(); if (!ProxyAccessHelper.allowNullLoader) {
checkProxyLoader(ccl, loader); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces); ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
} }
}
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) { if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded"); throw new IllegalArgumentException("interface limit exceeded");
} }
...@@ -698,6 +704,7 @@ public class Proxy implements java.io.Serializable { ...@@ -698,6 +704,7 @@ public class Proxy implements java.io.Serializable {
* if the invocation handler, {@code h}, is * if the invocation handler, {@code h}, is
* {@code null} * {@code null}
*/ */
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, Class<?>[] interfaces,
InvocationHandler h) InvocationHandler h)
...@@ -707,10 +714,15 @@ public class Proxy implements java.io.Serializable { ...@@ -707,10 +714,15 @@ public class Proxy implements java.io.Serializable {
throw new NullPointerException(); throw new NullPointerException();
} }
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
/* /*
* Look up or generate the designated proxy class. * Look up or generate the designated proxy class.
*/ */
Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor Class<?> cl = getProxyClass0(loader, interfaces);
/* /*
* Invoke its constructor with the designated invocation handler. * Invoke its constructor with the designated invocation handler.
...@@ -718,7 +730,6 @@ public class Proxy implements java.io.Serializable { ...@@ -718,7 +730,6 @@ public class Proxy implements java.io.Serializable {
try { try {
final Constructor<?> cons = cl.getConstructor(constructorParams); final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h; final InvocationHandler ih = h;
SecurityManager sm = System.getSecurityManager();
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may // create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission // implement non-public interfaces that requires a special permission
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package java.security; package java.security;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* <p> The AccessController class is used for access control operations * <p> The AccessController class is used for access control operations
...@@ -264,6 +266,7 @@ public final class AccessController { ...@@ -264,6 +266,7 @@ public final class AccessController {
* @see java.security.DomainCombiner * @see java.security.DomainCombiner
*/ */
@CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action); public static native <T> T doPrivileged(PrivilegedAction<T> action);
/** /**
...@@ -288,14 +291,15 @@ public final class AccessController { ...@@ -288,14 +291,15 @@ public final class AccessController {
* *
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
AccessControlContext acc = getStackAccessControlContext(); AccessControlContext acc = getStackAccessControlContext();
if (acc == null) { if (acc == null) {
return AccessController.doPrivileged(action); return AccessController.doPrivileged(action);
} }
DomainCombiner dc = acc.getAssignedCombiner(); DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action, preserveCombiner(dc)); return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
} }
...@@ -326,6 +330,7 @@ public final class AccessController { ...@@ -326,6 +330,7 @@ public final class AccessController {
* @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/ */
@CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action, public static native <T> T doPrivileged(PrivilegedAction<T> action,
AccessControlContext context); AccessControlContext context);
...@@ -353,6 +358,7 @@ public final class AccessController { ...@@ -353,6 +358,7 @@ public final class AccessController {
* @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
* @see java.security.DomainCombiner * @see java.security.DomainCombiner
*/ */
@CallerSensitive
public static native <T> T public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action) doPrivileged(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException; throws PrivilegedActionException;
...@@ -383,34 +389,29 @@ public final class AccessController { ...@@ -383,34 +389,29 @@ public final class AccessController {
* *
* @since 1.6 * @since 1.6
*/ */
public static <T> T doPrivilegedWithCombiner @CallerSensitive
(PrivilegedExceptionAction<T> action) throws PrivilegedActionException { public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException
{
AccessControlContext acc = getStackAccessControlContext(); AccessControlContext acc = getStackAccessControlContext();
if (acc == null) { if (acc == null) {
return AccessController.doPrivileged(action); return AccessController.doPrivileged(action);
} }
DomainCombiner dc = acc.getAssignedCombiner(); DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action, preserveCombiner(dc)); return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
} }
/** /**
* preserve the combiner across the doPrivileged call * preserve the combiner across the doPrivileged call
*/ */
private static AccessControlContext preserveCombiner private static AccessControlContext preserveCombiner(DomainCombiner combiner,
(DomainCombiner combiner) { Class<?> caller)
{
/**
* callerClass[0] = Reflection.getCallerClass
* callerClass[1] = AccessController.preserveCombiner
* callerClass[2] = AccessController.doPrivileged
* callerClass[3] = caller
*/
final Class<?> callerClass = sun.reflect.Reflection.getCallerClass(3);
ProtectionDomain callerPd = doPrivileged ProtectionDomain callerPd = doPrivileged
(new PrivilegedAction<ProtectionDomain>() { (new PrivilegedAction<ProtectionDomain>() {
public ProtectionDomain run() { public ProtectionDomain run() {
return callerClass.getProtectionDomain(); return caller.getProtectionDomain();
} }
}); });
...@@ -455,6 +456,7 @@ public final class AccessController { ...@@ -455,6 +456,7 @@ public final class AccessController {
* @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/ */
@CallerSensitive
public static native <T> T public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action, doPrivileged(PrivilegedExceptionAction<T> action,
AccessControlContext context) AccessControlContext context)
......
...@@ -30,6 +30,7 @@ import java.util.ServiceLoader; ...@@ -30,6 +30,7 @@ import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
...@@ -192,14 +193,11 @@ public class DriverManager { ...@@ -192,14 +193,11 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url, public static Connection getConnection(String url,
java.util.Properties info) throws SQLException { java.util.Properties info) throws SQLException {
// Gets the classloader of the code that called this method, may return (getConnection(url, info, Reflection.getCallerClass()));
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
return (getConnection(url, info, callerCL));
} }
/** /**
...@@ -226,14 +224,11 @@ public class DriverManager { ...@@ -226,14 +224,11 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url, public static Connection getConnection(String url,
String user, String password) throws SQLException { String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties(); java.util.Properties info = new java.util.Properties();
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
if (user != null) { if (user != null) {
info.put("user", user); info.put("user", user);
} }
...@@ -241,7 +236,7 @@ public class DriverManager { ...@@ -241,7 +236,7 @@ public class DriverManager {
info.put("password", password); info.put("password", password);
} }
return (getConnection(url, info, callerCL)); return (getConnection(url, info, Reflection.getCallerClass()));
} }
/** /**
...@@ -259,16 +254,12 @@ public class DriverManager { ...@@ -259,16 +254,12 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url) public static Connection getConnection(String url)
throws SQLException { throws SQLException {
java.util.Properties info = new java.util.Properties(); java.util.Properties info = new java.util.Properties();
return (getConnection(url, info, Reflection.getCallerClass()));
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
return (getConnection(url, info, callerCL));
} }
/** /**
...@@ -282,21 +273,20 @@ public class DriverManager { ...@@ -282,21 +273,20 @@ public class DriverManager {
* that can connect to the given URL * that can connect to the given URL
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
@CallerSensitive
public static Driver getDriver(String url) public static Driver getDriver(String url)
throws SQLException { throws SQLException {
println("DriverManager.getDriver(\"" + url + "\")"); println("DriverManager.getDriver(\"" + url + "\")");
// Gets the classloader of the code that called this method, may Class<?> callerClass = Reflection.getCallerClass();
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded registeredDrivers attempting to locate someone // Walk through the loaded registeredDrivers attempting to locate someone
// who understands the given URL. // who understands the given URL.
for (DriverInfo aDriver : registeredDrivers) { for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) { if(isDriverAllowed(aDriver.driver, callerClass)) {
try { try {
if(aDriver.driver.acceptsURL(url)) { if(aDriver.driver.acceptsURL(url)) {
// Success! // Success!
...@@ -350,20 +340,18 @@ public class DriverManager { ...@@ -350,20 +340,18 @@ public class DriverManager {
* @param driver the JDBC Driver to drop * @param driver the JDBC Driver to drop
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
@CallerSensitive
public static synchronized void deregisterDriver(Driver driver) public static synchronized void deregisterDriver(Driver driver)
throws SQLException { throws SQLException {
if (driver == null) { if (driver == null) {
return; return;
} }
// Gets the classloader of the code that called this method,
// may be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
println("DriverManager.deregisterDriver: " + driver); println("DriverManager.deregisterDriver: " + driver);
DriverInfo aDriver = new DriverInfo(driver); DriverInfo aDriver = new DriverInfo(driver);
if(registeredDrivers.contains(aDriver)) { if(registeredDrivers.contains(aDriver)) {
if (isDriverAllowed(driver, callerCL)) { if (isDriverAllowed(driver, Reflection.getCallerClass())) {
registeredDrivers.remove(aDriver); registeredDrivers.remove(aDriver);
} else { } else {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
...@@ -384,18 +372,17 @@ public class DriverManager { ...@@ -384,18 +372,17 @@ public class DriverManager {
* *
* @return the list of JDBC Drivers loaded by the caller's class loader * @return the list of JDBC Drivers loaded by the caller's class loader
*/ */
@CallerSensitive
public static java.util.Enumeration<Driver> getDrivers() { public static java.util.Enumeration<Driver> getDrivers() {
java.util.Vector<Driver> result = new java.util.Vector<>(); java.util.Vector<Driver> result = new java.util.Vector<>();
// Gets the classloader of the code that called this method, may Class<?> callerClass = Reflection.getCallerClass();
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded registeredDrivers. // Walk through the loaded registeredDrivers.
for(DriverInfo aDriver : registeredDrivers) { for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) { if(isDriverAllowed(aDriver.driver, callerClass)) {
result.addElement(aDriver.driver); result.addElement(aDriver.driver);
} else { } else {
println(" skipping: " + aDriver.getClass().getName()); println(" skipping: " + aDriver.getClass().getName());
...@@ -493,17 +480,13 @@ public class DriverManager { ...@@ -493,17 +480,13 @@ public class DriverManager {
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Internal method used to get the caller's class loader.
// Replaces the call to the native method
private static ClassLoader getCallerClassLoader() {
Class<?> cc = Reflection.getCallerClass(3);
ClassLoader cl = (cc != null) ? cc.getClassLoader() : null;
return cl;
}
// Indicates whether the class object that would be created if the code calling // Indicates whether the class object that would be created if the code calling
// DriverManager is accessible. // DriverManager is accessible.
private static boolean isDriverAllowed(Driver driver, Class<?> caller) {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
return isDriverAllowed(driver, callerCL);
}
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
boolean result = false; boolean result = false;
if(driver != null) { if(driver != null) {
...@@ -586,18 +569,19 @@ public class DriverManager { ...@@ -586,18 +569,19 @@ public class DriverManager {
// Worker method called by the public getConnection() methods. // Worker method called by the public getConnection() methods.
private static Connection getConnection( private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { String url, java.util.Properties info, Class<?> caller) throws SQLException {
/* /*
* When callerCl is null, we should check the application's * When callerCl is null, we should check the application's
* (which is invoking this class indirectly) * (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar * classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here. * can be loaded from here.
*/ */
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) { synchronized(DriverManager.class) {
// synchronize loading of the correct classloader. // synchronize loading of the correct classloader.
if(callerCL == null) { if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader(); callerCL = Thread.currentThread().getContextClassLoader();
} }
} }
if(url == null) { if(url == null) {
......
...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap; ...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.spi.ResourceBundleControlProvider; import java.util.spi.ResourceBundleControlProvider;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.util.locale.BaseLocale; import sun.util.locale.BaseLocale;
import sun.util.locale.LocaleObjectCache; import sun.util.locale.LocaleObjectCache;
...@@ -440,14 +442,10 @@ public abstract class ResourceBundle { ...@@ -440,14 +442,10 @@ public abstract class ResourceBundle {
/* /*
* Automatic determination of the ClassLoader to be used to load * Automatic determination of the ClassLoader to be used to load
* resources on behalf of the client. N.B. The client is getLoader's * resources on behalf of the client.
* caller's caller.
*/ */
private static ClassLoader getLoader() { private static ClassLoader getLoader(Class<?> caller) {
Class<?>[] stack = getClassContext(); ClassLoader cl = caller == null ? null : caller.getClassLoader();
/* Magic number 2 identifies our caller's caller */
Class<?> c = stack[2];
ClassLoader cl = (c == null) ? null : c.getClassLoader();
if (cl == null) { if (cl == null) {
// When the caller's loader is the boot class loader, cl is null // When the caller's loader is the boot class loader, cl is null
// here. In that case, ClassLoader.getSystemClassLoader() may // here. In that case, ClassLoader.getSystemClassLoader() may
...@@ -461,8 +459,6 @@ public abstract class ResourceBundle { ...@@ -461,8 +459,6 @@ public abstract class ResourceBundle {
return cl; return cl;
} }
private static native Class<?>[] getClassContext();
/** /**
* A wrapper of ClassLoader.getSystemClassLoader(). * A wrapper of ClassLoader.getSystemClassLoader().
*/ */
...@@ -746,11 +742,11 @@ public abstract class ResourceBundle { ...@@ -746,11 +742,11 @@ public abstract class ResourceBundle {
* if no resource bundle for the specified base name can be found * if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and the default locale * @return a resource bundle for the given base name and the default locale
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName) public static final ResourceBundle getBundle(String baseName)
{ {
return getBundleImpl(baseName, Locale.getDefault(), return getBundleImpl(baseName, Locale.getDefault(),
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
getDefaultControl(baseName)); getDefaultControl(baseName));
} }
...@@ -788,11 +784,11 @@ public abstract class ResourceBundle { ...@@ -788,11 +784,11 @@ public abstract class ResourceBundle {
* needed. * needed.
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, public static final ResourceBundle getBundle(String baseName,
Control control) { Control control) {
return getBundleImpl(baseName, Locale.getDefault(), return getBundleImpl(baseName, Locale.getDefault(),
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
control); control);
} }
...@@ -817,12 +813,12 @@ public abstract class ResourceBundle { ...@@ -817,12 +813,12 @@ public abstract class ResourceBundle {
* if no resource bundle for the specified base name can be found * if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale * @return a resource bundle for the given base name and locale
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, public static final ResourceBundle getBundle(String baseName,
Locale locale) Locale locale)
{ {
return getBundleImpl(baseName, locale, return getBundleImpl(baseName, locale,
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
getDefaultControl(baseName)); getDefaultControl(baseName));
} }
...@@ -863,11 +859,11 @@ public abstract class ResourceBundle { ...@@ -863,11 +859,11 @@ public abstract class ResourceBundle {
* needed. * needed.
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, Locale targetLocale, public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
Control control) { Control control) {
return getBundleImpl(baseName, targetLocale, return getBundleImpl(baseName, targetLocale,
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
control); control);
} }
...@@ -1721,8 +1717,9 @@ public abstract class ResourceBundle { ...@@ -1721,8 +1717,9 @@ public abstract class ResourceBundle {
* @since 1.6 * @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale) * @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/ */
@CallerSensitive
public static final void clearCache() { public static final void clearCache() {
clearCache(getLoader()); clearCache(getLoader(Reflection.getCallerClass()));
} }
/** /**
......
...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic; ...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator; import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
...@@ -77,8 +80,9 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -77,8 +80,9 @@ public abstract class AtomicIntegerFieldUpdater<T> {
* or the field is inaccessible to the caller according to Java language * or the field is inaccessible to the caller according to Java language
* access control * access control
*/ */
@CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName); return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());
} }
/** /**
...@@ -365,9 +369,11 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -365,9 +369,11 @@ public abstract class AtomicIntegerFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName) { AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
final String fieldName,
final Class<?> caller)
{
final Field field; final Field field;
final Class<?> caller;
final int modifiers; final int modifiers;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -376,7 +382,6 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -376,7 +382,6 @@ public abstract class AtomicIntegerFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
......
...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic; ...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
import java.util.function.LongUnaryOperator; import java.util.function.LongUnaryOperator;
import java.util.function.LongBinaryOperator; import java.util.function.LongBinaryOperator;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
...@@ -77,11 +80,13 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -77,11 +80,13 @@ public abstract class AtomicLongFieldUpdater<T> {
* or the field is inaccessible to the caller according to Java language * or the field is inaccessible to the caller according to Java language
* access control * access control
*/ */
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS) if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName); return new CASUpdater<U>(tclass, fieldName, caller);
else else
return new LockedUpdater<U>(tclass, fieldName); return new LockedUpdater<U>(tclass, fieldName, caller);
} }
/** /**
...@@ -365,9 +370,8 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -365,9 +370,8 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
CASUpdater(final Class<T> tclass, final String fieldName) { CASUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
final Field field; final Field field;
final Class<?> caller;
final int modifiers; final int modifiers;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -376,7 +380,6 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -376,7 +380,6 @@ public abstract class AtomicLongFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
...@@ -490,9 +493,8 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -490,9 +493,8 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
LockedUpdater(final Class<T> tclass, final String fieldName) { LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
Field field = null; Field field = null;
Class<?> caller = null;
int modifiers = 0; int modifiers = 0;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -501,7 +503,6 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -501,7 +503,6 @@ public abstract class AtomicLongFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
......
...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic; ...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import java.util.function.BinaryOperator; import java.util.function.BinaryOperator;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
...@@ -96,10 +99,12 @@ public abstract class AtomicReferenceFieldUpdater<T, V> { ...@@ -96,10 +99,12 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
* or the field is inaccessible to the caller according to Java language * or the field is inaccessible to the caller according to Java language
* access control * access control
*/ */
@CallerSensitive
public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) { public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass, return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
vclass, vclass,
fieldName); fieldName,
Reflection.getCallerClass());
} }
/** /**
...@@ -297,10 +302,11 @@ public abstract class AtomicReferenceFieldUpdater<T, V> { ...@@ -297,10 +302,11 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass, AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
Class<V> vclass, Class<V> vclass,
final String fieldName) { final String fieldName,
final Class<?> caller)
{
final Field field; final Field field;
final Class<?> fieldClass; final Class<?> fieldClass;
final Class<?> caller;
final int modifiers; final int modifiers;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -309,7 +315,6 @@ public abstract class AtomicReferenceFieldUpdater<T, V> { ...@@ -309,7 +315,6 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
......
...@@ -36,6 +36,8 @@ import java.util.MissingResourceException; ...@@ -36,6 +36,8 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Supplier; import java.util.function.Supplier;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* A Logger object is used to log messages for a specific * A Logger object is used to log messages for a specific
...@@ -333,13 +335,10 @@ public class Logger { ...@@ -333,13 +335,10 @@ public class Logger {
} }
} }
private static Logger demandLogger(String name, String resourceBundleName) { private static Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
LogManager manager = LogManager.getLogManager(); LogManager manager = LogManager.getLogManager();
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null && !SystemLoggerHelper.disableCallerCheck) { if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
// 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller
final int SKIP_FRAMES = 3;
Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
if (caller.getClassLoader() == null) { if (caller.getClassLoader() == null) {
return manager.demandSystemLogger(name, resourceBundleName); return manager.demandSystemLogger(name, resourceBundleName);
} }
...@@ -377,6 +376,7 @@ public class Logger { ...@@ -377,6 +376,7 @@ public class Logger {
// Synchronization is not required here. All synchronization for // Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger(). // adding a new Logger object is handled by LogManager.addLogger().
@CallerSensitive
public static Logger getLogger(String name) { public static Logger getLogger(String name) {
// This method is intentionally not a wrapper around a call // This method is intentionally not a wrapper around a call
// to getLogger(name, resourceBundleName). If it were then // to getLogger(name, resourceBundleName). If it were then
...@@ -388,7 +388,7 @@ public class Logger { ...@@ -388,7 +388,7 @@ public class Logger {
// would throw an IllegalArgumentException in the second call // would throw an IllegalArgumentException in the second call
// because the wrapper would result in an attempt to replace // because the wrapper would result in an attempt to replace
// the existing "resourceBundleForFoo" with null. // the existing "resourceBundleForFoo" with null.
return demandLogger(name, null); return demandLogger(name, null, Reflection.getCallerClass());
} }
/** /**
...@@ -434,8 +434,9 @@ public class Logger { ...@@ -434,8 +434,9 @@ public class Logger {
// Synchronization is not required here. All synchronization for // Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger(). // adding a new Logger object is handled by LogManager.addLogger().
@CallerSensitive
public static Logger getLogger(String name, String resourceBundleName) { public static Logger getLogger(String name, String resourceBundleName) {
Logger result = demandLogger(name, resourceBundleName); Logger result = demandLogger(name, resourceBundleName, Reflection.getCallerClass());
// MissingResourceException or IllegalArgumentException can be // MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo(). // thrown by setupResourceInfo().
......
...@@ -28,6 +28,7 @@ import java.util.*; ...@@ -28,6 +28,7 @@ import java.util.*;
import java.security.*; import java.security.*;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.ServiceConfigurationError; import java.util.ServiceConfigurationError;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -60,9 +61,10 @@ public class ScriptEngineManager { ...@@ -60,9 +61,10 @@ public class ScriptEngineManager {
* *
* @see java.lang.Thread#getContextClassLoader * @see java.lang.Thread#getContextClassLoader
*/ */
@CallerSensitive
public ScriptEngineManager() { public ScriptEngineManager() {
ClassLoader ctxtLoader = Thread.currentThread().getContextClassLoader(); ClassLoader ctxtLoader = Thread.currentThread().getContextClassLoader();
if (canCallerAccessLoader(ctxtLoader)) { if (canCallerAccessLoader(ctxtLoader, Reflection.getCallerClass())) {
if (DEBUG) System.out.println("using " + ctxtLoader); if (DEBUG) System.out.println("using " + ctxtLoader);
init(ctxtLoader); init(ctxtLoader);
} else { } else {
...@@ -419,10 +421,10 @@ public class ScriptEngineManager { ...@@ -419,10 +421,10 @@ public class ScriptEngineManager {
/** Global bindings associated with script engines created by this manager. */ /** Global bindings associated with script engines created by this manager. */
private Bindings globalScope; private Bindings globalScope;
private boolean canCallerAccessLoader(ClassLoader loader) { private boolean canCallerAccessLoader(ClassLoader loader, Class<?> caller) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader callerLoader = getCallerClassLoader(); ClassLoader callerLoader = getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) { if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) {
if (loader != callerLoader || !isAncestor(loader, callerLoader)) { if (loader != callerLoader || !isAncestor(loader, callerLoader)) {
try { try {
...@@ -438,10 +440,9 @@ public class ScriptEngineManager { ...@@ -438,10 +440,9 @@ public class ScriptEngineManager {
return true; return true;
} }
// Note that this code is same as ClassLoader.getCallerClassLoader(). // Note that this code is same as ClassLoader.getClassLoader().
// But, that method is package private and hence we can't call here. // But, that method is package private and hence we can't call here.
private ClassLoader getCallerClassLoader() { private ClassLoader getClassLoader(Class<?> caller) {
Class<?> caller = Reflection.getCallerClass(3);
if (caller == null) { if (caller == null) {
return null; return null;
} }
......
...@@ -28,6 +28,9 @@ package sun.misc; ...@@ -28,6 +28,9 @@ package sun.misc;
import java.security.*; import java.security.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* A collection of methods for performing low-level, unsafe operations. * A collection of methods for performing low-level, unsafe operations.
...@@ -80,9 +83,10 @@ public final class Unsafe { ...@@ -80,9 +83,10 @@ public final class Unsafe {
* <code>checkPropertiesAccess</code> method doesn't allow * <code>checkPropertiesAccess</code> method doesn't allow
* access to the system properties. * access to the system properties.
*/ */
@CallerSensitive
public static Unsafe getUnsafe() { public static Unsafe getUnsafe() {
Class<?> cc = sun.reflect.Reflection.getCallerClass(2); Class<?> caller = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(cc.getClassLoader())) if (!VM.isSystemDomainLoader(caller.getClassLoader()))
throw new SecurityException("Unsafe"); throw new SecurityException("Unsafe");
return theUnsafe; return theUnsafe;
} }
...@@ -817,8 +821,6 @@ public final class Unsafe { ...@@ -817,8 +821,6 @@ public final class Unsafe {
ClassLoader loader, ClassLoader loader,
ProtectionDomain protectionDomain); ProtectionDomain protectionDomain);
public native Class<?> defineClass(String name, byte[] b, int off, int len);
/** /**
* Define a class but do not make it known to the class loader or system dictionary. * Define a class but do not make it known to the class loader or system dictionary.
* <p> * <p>
......
/* /*
* Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,13 +23,19 @@ ...@@ -23,13 +23,19 @@
* questions. * questions.
*/ */
#include "jni.h" package sun.reflect;
#include "jvm.h"
#include "java_util_ResourceBundle.h" import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
JNIEXPORT jobjectArray JNICALL /**
Java_java_util_ResourceBundle_getClassContext(JNIEnv *env, jobject this) * A method annotated @CallerSensitive is sensitive to its calling class,
{ * via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass},
return JVM_GetClassContext(env); * or via some equivalent.
*
* @author John R. Rose
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({CONSTRUCTOR, METHOD})
public @interface CallerSensitive {
} }
...@@ -51,16 +51,11 @@ public class Reflection { ...@@ -51,16 +51,11 @@ public class Reflection {
methodFilterMap = new HashMap<>(); methodFilterMap = new HashMap<>();
} }
/** Returns the class of the method <code>realFramesToSkip</code> /** Returns the class of the caller of the method calling this method,
frames up the stack (zero-based), ignoring frames associated ignoring frames associated with java.lang.reflect.Method.invoke()
with java.lang.reflect.Method.invoke() and its implementation. and its implementation. */
The first frame is that associated with this method, so @CallerSensitive
<code>getCallerClass(0)</code> returns the Class object for public static native Class<?> getCallerClass();
sun.reflect.Reflection. Frames associated with
java.lang.reflect.Method.invoke() and its implementation are
completely ignored and do not count toward the number of "real"
frames skipped. */
public static native Class<?> getCallerClass(int realFramesToSkip);
/** Retrieves the access flags written to the class file. For /** Retrieves the access flags written to the class file. For
inner classes these flags may differ from those returned by inner classes these flags may differ from those returned by
...@@ -321,4 +316,27 @@ public class Reflection { ...@@ -321,4 +316,27 @@ public class Reflection {
} }
return newMembers; return newMembers;
} }
/**
* Tests if the given method is caller-sensitive and the declaring class
* is defined by either the bootstrap class loader or extension class loader.
*/
public static boolean isCallerSensitive(Method m) {
final ClassLoader loader = m.getDeclaringClass().getClassLoader();
if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) {
return m.isAnnotationPresent(CallerSensitive.class);
}
return false;
}
private static boolean isExtClassLoader(ClassLoader loader) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
while (cl != null) {
if (cl.getParent() == null && cl == loader) {
return true;
}
cl = cl.getParent();
}
return false;
}
} }
...@@ -350,16 +350,21 @@ JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim); ...@@ -350,16 +350,21 @@ JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
/* /*
* java.lang.Class and java.lang.ClassLoader * java.lang.Class and java.lang.ClassLoader
*/ */
#define JVM_DEPTH -1
/* /*
* Returns the class in which the code invoking the native method * Returns the immediate caller class of the native method invoking
* belongs. * JVM_GetCallerClass. The Method.invoke and other frames due to
* reflection machinery are skipped.
* *
* Note that in JDK 1.1, native methods did not create a frame. * The depth parameter must be -1 (JVM_DEPTH). The caller is expected
* In 1.2, they do. Therefore native methods like Class.forName * to be marked with sun.reflect.CallerSensitive. The JVM will throw
* can no longer look at the current frame for the caller class. * an error if it is not marked propertly.
*/ */
JNIEXPORT jclass JNICALL JNIEXPORT jclass JNICALL
JVM_GetCallerClass(JNIEnv *env, int n); JVM_GetCallerClass(JNIEnv *env, int depth);
/* /*
* Find primitive classes * Find primitive classes
......
...@@ -492,24 +492,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find ...@@ -492,24 +492,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find
(*env)->ReleaseStringUTFChars(env, name, cname); (*env)->ReleaseStringUTFChars(env, name, cname);
return res; return res;
} }
JNIEXPORT jobject JNICALL
Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
{
jobjectArray jcallerStack;
int len;
jcallerStack = JVM_GetClassContext(env);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
len = (*env)->GetArrayLength(env, jcallerStack);
if (index < len) {
return (*env)->GetObjectArrayElement(env, jcallerStack, index);
}
return NULL;
}
/* /*
* Class: java_lang_ClassLoader_NativeLibrary * Class: java_lang_ClassLoader_NativeLibrary
* Method: findBuiltinLib * Method: findBuiltinLib
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "java_lang_SecurityManager.h" #include "java_lang_SecurityManager.h"
#include "java_lang_ClassLoader.h" #include "java_lang_ClassLoader.h"
#include "java_util_ResourceBundle.h"
/* /*
* Make sure a security manager instance is initialized. * Make sure a security manager instance is initialized.
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
#include "sun_reflect_Reflection.h" #include "sun_reflect_Reflection.h"
JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass
(JNIEnv *env, jclass unused, jint depth) (JNIEnv *env, jclass unused)
{ {
return JVM_GetCallerClass(env, depth); return JVM_GetCallerClass(env, JVM_DEPTH); // JVM_DEPTH is only the expected value
} }
JNIEXPORT jint JNICALL Java_sun_reflect_Reflection_getClassAccessFlags JNIEXPORT jint JNICALL Java_sun_reflect_Reflection_getClassAccessFlags
......
...@@ -478,7 +478,7 @@ jdk_io: $(call TestDirs, java/io) ...@@ -478,7 +478,7 @@ jdk_io: $(call TestDirs, java/io)
# Stable agentvm testruns (minus items from PROBLEM_LIST) # Stable agentvm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_lang JDK_ALL_TARGETS += jdk_lang
JDK_DEFAULT_TARGETS += jdk_lang JDK_DEFAULT_TARGETS += jdk_lang
jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc vm) jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc sun/reflect vm)
$(call RunAgentvmBatch) $(call RunAgentvmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST) # Stable othervm testruns (minus items from PROBLEM_LIST)
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.tools.classfile.*;
import com.sun.tools.jdeps.ClassFileReader;
import static com.sun.tools.classfile.ConstantPool.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
/*
* @test
* @bug 8010117
* @summary Verify if CallerSensitive methods are annotated with
* sun.reflect.CallerSensitive annotation
* @build CallerSensitiveFinder MethodFinder
* @run main/othervm/timeout=900 -mx600m CallerSensitiveFinder
*/
public class CallerSensitiveFinder extends MethodFinder {
private static int numThreads = 3;
private static boolean verbose = false;
public static void main(String[] args) throws Exception {
List<Path> classes = new ArrayList<>();
String testclasses = System.getProperty("test.classes", ".");
int i = 0;
while (i < args.length) {
String arg = args[i++];
if (arg.equals("-v")) {
verbose = true;
} else {
Path p = Paths.get(testclasses, arg);
if (!p.toFile().exists()) {
throw new IllegalArgumentException(arg + " does not exist");
}
classes.add(p);
}
}
if (classes.isEmpty()) {
classes.addAll(PlatformClassPath.getJREClasses());
}
final String method = "sun/reflect/Reflection.getCallerClass";
CallerSensitiveFinder csfinder = new CallerSensitiveFinder(method);
List<String> errors = csfinder.run(classes);
if (!errors.isEmpty()) {
throw new RuntimeException(errors.size() +
" caller-sensitive methods are missing @CallerSensitive annotation");
}
}
private final List<String> csMethodsMissingAnnotation = new ArrayList<>();
public CallerSensitiveFinder(String... methods) {
super(methods);
}
public List<String> run(List<Path> classes) throws IOException, InterruptedException,
ExecutionException, ConstantPoolException
{
ExecutorService pool = Executors.newFixedThreadPool(numThreads);
for (Path path : classes) {
ClassFileReader reader = ClassFileReader.newInstance(path.toFile());
for (ClassFile cf : reader.getClassFiles()) {
String classFileName = cf.getName();
// for each ClassFile
// parse constant pool to find matching method refs
// parse each method (caller)
// - visit and find method references matching the given method name
pool.submit(getTask(cf));
}
}
waitForCompletion();
pool.shutdown();
return csMethodsMissingAnnotation;
}
private static final String CALLER_SENSITIVE_ANNOTATION = "Lsun/reflect/CallerSensitive;";
private static boolean isCallerSensitive(Method m, ConstantPool cp)
throws ConstantPoolException
{
RuntimeAnnotations_attribute attr =
(RuntimeAnnotations_attribute)m.attributes.get(Attribute.RuntimeVisibleAnnotations);
int index = 0;
if (attr != null) {
for (int i = 0; i < attr.annotations.length; i++) {
Annotation ann = attr.annotations[i];
String annType = cp.getUTF8Value(ann.type_index);
if (CALLER_SENSITIVE_ANNOTATION.equals(annType)) {
return true;
}
}
}
return false;
}
public void referenceFound(ClassFile cf, Method m, Set<Integer> refs)
throws ConstantPoolException
{
String name = String.format("%s#%s %s", cf.getName(),
m.getName(cf.constant_pool),
m.descriptor.getValue(cf.constant_pool));
if (!CallerSensitiveFinder.isCallerSensitive(m, cf.constant_pool)) {
csMethodsMissingAnnotation.add(name);
System.err.println("Missing @CallerSensitive: " + name);
} else {
if (verbose) {
System.out.format("@CS %s%n", name);
}
}
}
private final List<FutureTask<String>> tasks = new ArrayList<FutureTask<String>>();
private FutureTask<String> getTask(final ClassFile cf) {
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
return parse(cf);
}
});
tasks.add(task);
return task;
}
private void waitForCompletion() throws InterruptedException, ExecutionException {
for (FutureTask<String> t : tasks) {
String s = t.get();
}
System.out.println("Parsed " + tasks.size() + " classfiles");
}
static class PlatformClassPath {
static List<Path> getJREClasses() throws IOException {
List<Path> result = new ArrayList<Path>();
Path home = Paths.get(System.getProperty("java.home"));
if (home.endsWith("jre")) {
// jar files in <javahome>/jre/lib
// skip <javahome>/lib
result.addAll(addJarFiles(home.resolve("lib")));
} else if (home.resolve("lib").toFile().exists()) {
// either a JRE or a jdk build image
File classes = home.resolve("classes").toFile();
if (classes.exists() && classes.isDirectory()) {
// jdk build outputdir
result.add(classes.toPath());
}
// add other JAR files
result.addAll(addJarFiles(home.resolve("lib")));
} else {
throw new RuntimeException("\"" + home + "\" not a JDK home");
}
return result;
}
static List<Path> addJarFiles(final Path root) throws IOException {
final List<Path> result = new ArrayList<Path>();
final Path ext = root.resolve("ext");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
if (dir.equals(root) || dir.equals(ext)) {
return FileVisitResult.CONTINUE;
} else {
// skip other cobundled JAR files
return FileVisitResult.SKIP_SUBTREE;
}
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
File f = file.toFile();
String fn = f.getName();
// parse alt-rt.jar as well
if (fn.endsWith(".jar") && !fn.equals("jfxrt.jar")) {
result.add(file);
}
return FileVisitResult.CONTINUE;
}
});
return result;
}
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.*;
import com.sun.tools.classfile.*;
import static com.sun.tools.classfile.ConstantPool.*;
import com.sun.tools.classfile.Instruction.TypeKind;
/**
* MethodFinder utility class to find references to the given methods.
*/
public abstract class MethodFinder {
final List<String> methods;
public MethodFinder(String... methods) {
this.methods = Arrays.asList(methods);
}
/**
* A callback method will be invoked when a method referencing
* any of the lookup methods.
*
* @param cf ClassFile
* @param m Method
* @param refs Set of constant pool indices that reference the methods
* matching the given lookup method names
*/
public abstract void referenceFound(ClassFile cf, Method m, Set<Integer> refs)
throws ConstantPoolException;
public String parse(ClassFile cf) throws ConstantPoolException {
List<Integer> cprefs = new ArrayList<Integer>();
int index = 1;
for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) {
if (cpInfo.accept(cpVisitor, null)) {
cprefs.add(index);
}
index += cpInfo.size();
}
if (!cprefs.isEmpty()) {
for (Method m : cf.methods) {
Set<Integer> refs = new HashSet<Integer>();
Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
if (c_attr != null) {
for (Instruction instr : c_attr.getInstructions()) {
int idx = instr.accept(codeVisitor, cprefs);
if (idx > 0) {
refs.add(idx);
}
}
}
if (refs.size() > 0) {
referenceFound(cf, m, refs);
}
}
}
return cprefs.isEmpty() ? "" : cf.getName();
}
private ConstantPool.Visitor<Boolean,Void> cpVisitor =
new ConstantPool.Visitor<Boolean,Void>()
{
private boolean matches(CPRefInfo info) {
try {
CONSTANT_NameAndType_info nat = info.getNameAndTypeInfo();
return matches(info.getClassName(), nat.getName(), nat.getType());
} catch (ConstantPoolException ex) {
return false;
}
}
private boolean matches(String cn, String name, String type) {
return methods.contains(cn + "." + name);
}
public Boolean visitClass(CONSTANT_Class_info info, Void p) {
return false;
}
public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
return matches(info);
}
public Boolean visitMethodref(CONSTANT_Methodref_info info, Void p) {
return matches(info);
}
public Boolean visitDouble(CONSTANT_Double_info info, Void p) {
return false;
}
public Boolean visitFieldref(CONSTANT_Fieldref_info info, Void p) {
return false;
}
public Boolean visitFloat(CONSTANT_Float_info info, Void p) {
return false;
}
public Boolean visitInteger(CONSTANT_Integer_info info, Void p) {
return false;
}
public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
return false;
}
public Boolean visitLong(CONSTANT_Long_info info, Void p) {
return false;
}
public Boolean visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
return false;
}
public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
return false;
}
public Boolean visitMethodType(CONSTANT_MethodType_info info, Void p) {
return false;
}
public Boolean visitString(CONSTANT_String_info info, Void p) {
return false;
}
public Boolean visitUtf8(CONSTANT_Utf8_info info, Void p) {
return false;
}
};
private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor =
new Instruction.KindVisitor<Integer, List<Integer>>()
{
public Integer visitNoOperands(Instruction instr, List<Integer> p) {
return 0;
}
public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {
return 0;
}
public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {
return 0;
}
public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {
return p.contains(index) ? index : 0;
}
public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {
return p.contains(index) ? index : 0;
}
public Integer visitLocal(Instruction instr, int index, List<Integer> p) {
return 0;
}
public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {
return 0;
}
public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {
return 0;
}
public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {
return 0;
}
public Integer visitValue(Instruction instr, int value, List<Integer> p) {
return 0;
}
public Integer visitUnknown(Instruction instr, List<Integer> p) {
return 0;
}
};
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8010117
* @summary Test CallerSensitiveFinder to find missing annotation
* @compile -XDignore.symbol.file MissingCallerSensitive.java
* @build CallerSensitiveFinder MethodFinder
* @run main MissingCallerSensitive
*/
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
public class MissingCallerSensitive {
public static void main(String[] args) throws Exception {
String testclasses = System.getProperty("test.classes", ".");
List<Path> classes = new ArrayList<>();
classes.add(Paths.get(testclasses, "MissingCallerSensitive.class"));
final String method = "sun/reflect/Reflection.getCallerClass";
CallerSensitiveFinder csfinder = new CallerSensitiveFinder(method);
List<String> errors = csfinder.run(classes);
if (errors.size() != 1) {
throw new RuntimeException("Unexpected number of methods found: " + errors.size());
}
String m = errors.get(0);
if (!m.startsWith("MissingCallerSensitive#missingCallerSensitiveAnnotation")) {
throw new RuntimeException("Unexpected method missing annotation: " + m);
}
}
@sun.reflect.CallerSensitive
public ClassLoader getCallerLoader() {
Class<?> c = sun.reflect.Reflection.getCallerClass();
return c.getClassLoader();
}
public ClassLoader missingCallerSensitiveAnnotation() {
Class<?> c = sun.reflect.Reflection.getCallerClass();
return c.getClassLoader();
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package boot;
public class GetCallerClass {
@sun.reflect.CallerSensitive
public ClassLoader getCallerLoader() {
Class<?> c = sun.reflect.Reflection.getCallerClass();
return c.getClassLoader();
}
public ClassLoader missingCallerSensitiveAnnotation() {
Class<?> c = sun.reflect.Reflection.getCallerClass();
return c.getClassLoader();
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import boot.GetCallerClass;
import java.lang.reflect.*;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
public class GetCallerClassTest {
private final GetCallerClass gcc; // boot.GetCallerClass is in bootclasspath
GetCallerClassTest() {
this.gcc = new GetCallerClass();
}
public static void main(String[] args) throws Exception {
GetCallerClassTest gcct = new GetCallerClassTest();
// ensure methods are annotated with @CallerSensitive
ensureAnnotationPresent(boot.GetCallerClass.class, "getCallerLoader", true);
ensureAnnotationPresent(GetCallerClassTest.class, "testNonSystemMethod", false);
// call Reflection.getCallerClass from bootclasspath with and without @CS
gcct.testCallerSensitiveMethods();
// call Reflection.getCallerClass from classpath with @CS
gcct.testNonSystemMethod();
}
private static void ensureAnnotationPresent(Class<?> c, String name, boolean cs)
throws NoSuchMethodException
{
Method m = c.getDeclaredMethod(name);
if (!m.isAnnotationPresent(CallerSensitive.class)) {
throw new RuntimeException("@CallerSensitive not present in method " + m);
}
if (Reflection.isCallerSensitive(m) != cs) {
throw new RuntimeException("Unexpected: isCallerSensitive returns " +
Reflection.isCallerSensitive(m));
}
}
private void testCallerSensitiveMethods() {
try {
ClassLoader cl = gcc.getCallerLoader();
if (cl != GetCallerClassTest.class.getClassLoader()) {
throw new RuntimeException("mismatched class loader");
}
gcc.missingCallerSensitiveAnnotation();
throw new RuntimeException("getCallerLoader not marked with @CallerSensitive");
} catch (InternalError e) {
StackTraceElement[] stackTrace = e.getStackTrace();
checkStackTrace(stackTrace, e);
if (!stackTrace[1].getClassName().equals(GetCallerClass.class.getName()) ||
!stackTrace[1].getMethodName().equals("missingCallerSensitiveAnnotation")) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
if (!stackTrace[2].getClassName().equals(GetCallerClassTest.class.getName()) ||
!stackTrace[2].getMethodName().equals("testCallerSensitiveMethods")) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
System.out.println("Expected error: " + e.getMessage());
}
}
@CallerSensitive
private void testNonSystemMethod() {
try {
Class<?> c = Reflection.getCallerClass();
throw new RuntimeException("@CallerSensitive testNonSystemMethods not supported");
} catch (InternalError e) {
StackTraceElement[] stackTrace = e.getStackTrace();
checkStackTrace(stackTrace, e);
if (!stackTrace[1].getClassName().equals(GetCallerClassTest.class.getName()) ||
!stackTrace[1].getMethodName().equals("testNonSystemMethod")) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
if (!stackTrace[2].getClassName().equals(GetCallerClassTest.class.getName()) ||
!stackTrace[2].getMethodName().equals("main")) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
System.out.println("Expected error: " + e.getMessage());
}
}
private void checkStackTrace(StackTraceElement[] stackTrace, Error e) {
if (stackTrace.length < 3) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
if (!stackTrace[0].getClassName().equals("sun.reflect.Reflection") ||
!stackTrace[0].getMethodName().equals("getCallerClass")) {
throw new RuntimeException("Unexpected error: " + e.getMessage(), e);
}
}
}
#
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @bug 8010117
# @summary Test if the VM enforces sun.reflect.Reflection.getCallerClass
# be called by methods annotated with sun.reflect.CallerSensitive
#
# @run shell GetCallerClassTest.sh
if [ "${TESTSRC}" = "" ]
then
echo "TESTSRC not set. Test cannot execute. Failed."
exit 1
fi
echo "TESTSRC=${TESTSRC}"
if [ "${TESTJAVA}" = "" ]
then
echo "TESTJAVA not set. Test cannot execute. Failed."
exit 1
fi
echo "TESTJAVA=${TESTJAVA}"
if [ "${COMPILEJAVA}" = "" ]
then
COMPILEJAVA="${TESTJAVA}"
fi
echo "COMPILEJAVA=${COMPILEJAVA}"
if [ "${TESTCLASSES}" = "" ]
then
echo "TESTCLASSES not set. Test cannot execute. Failed."
exit 1
fi
BCP=${TESTCLASSES}/bcp
rm -rf ${BCP}
mkdir ${BCP}
# Compile GetCallerClass in bootclasspath
${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
-XDignore.symbol.file \
-d ${BCP} ${TESTSRC}/GetCallerClass.java || exit 1
${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
-XDignore.symbol.file -Xbootclasspath/a:${BCP} \
-d ${TESTCLASSES} ${TESTSRC}/GetCallerClassTest.java || exit 2
${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbootclasspath/a:${BCP} \
-cp ${TESTCLASSES} GetCallerClassTest || exit 3
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册