8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
Reviewed-by: jrose, alanb, twisti
This commit is contained in:
parent
dfcf6055a7
commit
176ed8d94c
@ -48,7 +48,6 @@ FILES_c = \
|
||||
Proxy.c \
|
||||
RandomAccessFile.c \
|
||||
RandomAccessFile_md.c \
|
||||
ResourceBundle.c \
|
||||
Runtime.c \
|
||||
SecurityManager.c \
|
||||
Shutdown.c \
|
||||
|
@ -134,7 +134,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_load;
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
|
||||
Java_java_lang_ClassLoader_getCaller;
|
||||
Java_java_lang_ClassLoader_registerNatives;
|
||||
Java_java_lang_Compiler_registerNatives;
|
||||
Java_java_lang_Double_longBitsToDouble;
|
||||
@ -233,7 +232,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
|
||||
Java_java_security_AccessController_getStackAccessControlContext;
|
||||
Java_java_security_AccessController_getInheritedAccessControlContext;
|
||||
Java_java_util_ResourceBundle_getClassContext;
|
||||
Java_java_util_TimeZone_getSystemTimeZoneID;
|
||||
Java_java_util_TimeZone_getSystemGMTOffsetID;
|
||||
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
|
||||
|
@ -73,7 +73,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -78,7 +78,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -74,7 +74,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -134,7 +134,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_load;
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_unload;
|
||||
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
|
||||
Java_java_lang_ClassLoader_getCaller;
|
||||
Java_java_lang_ClassLoader_registerNatives;
|
||||
Java_java_lang_Compiler_registerNatives;
|
||||
Java_java_lang_Double_longBitsToDouble;
|
||||
@ -233,7 +232,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
|
||||
Java_java_security_AccessController_getStackAccessControlContext;
|
||||
Java_java_security_AccessController_getInheritedAccessControlContext;
|
||||
Java_java_util_ResourceBundle_getClassContext;
|
||||
Java_java_util_TimeZone_getSystemTimeZoneID;
|
||||
Java_java_util_TimeZone_getSystemGMTOffsetID;
|
||||
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
|
||||
|
@ -78,7 +78,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -74,7 +74,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -73,7 +73,6 @@ text: .text%writeBytes;
|
||||
# Test Sleep
|
||||
# Test IntToString
|
||||
# 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%JNU_GetEnv;
|
||||
text: .text%Java_java_io_UnixFileSystem_checkAccess;
|
||||
|
@ -53,6 +53,7 @@ import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import sun.misc.Unsafe;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.ConstantPool;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.ReflectionFactory;
|
||||
@ -250,9 +251,11 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* by this method fails
|
||||
* @exception ClassNotFoundException if the class cannot be located
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Class<?> forName(String className)
|
||||
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,
|
||||
* @see java.lang.ClassLoader
|
||||
* @since 1.2
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Class<?> forName(String name, boolean initialize,
|
||||
ClassLoader loader)
|
||||
throws ClassNotFoundException
|
||||
@ -324,7 +328,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
if (sun.misc.VM.isSystemDomainLoader(loader)) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = ClassLoader.getCallerClassLoader();
|
||||
ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
|
||||
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
|
||||
sm.checkPermission(
|
||||
SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
@ -386,18 +390,14 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
@CallerSensitive
|
||||
public T newInstance()
|
||||
throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
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
|
||||
// the current Java memory model.
|
||||
|
||||
@ -432,7 +432,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
// Security check (same as in java.lang.reflect.Constructor)
|
||||
int modifiers = tmpConstructor.getModifiers();
|
||||
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass(3);
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (newInstanceCallerCache != caller) {
|
||||
Reflection.ensureMemberAccess(caller, this, null, modifiers);
|
||||
newInstanceCallerCache = caller;
|
||||
@ -674,16 +674,14 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* @see SecurityManager#checkPermission
|
||||
* @see java.lang.RuntimePermission
|
||||
*/
|
||||
@CallerSensitive
|
||||
public ClassLoader getClassLoader() {
|
||||
ClassLoader cl = getClassLoader0();
|
||||
if (cl == null)
|
||||
return null;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = ClassLoader.getCallerClassLoader();
|
||||
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
@ -1392,11 +1390,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Class<?>[] getClasses() {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
|
||||
|
||||
// Privileged so this implementation can look at DECLARED classes,
|
||||
// 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,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Field[] getFields() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
return copyFields(privateGetPublicFields(null));
|
||||
}
|
||||
|
||||
@ -1518,11 +1512,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Method[] getMethods() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
return copyMethods(privateGetPublicMethods());
|
||||
}
|
||||
|
||||
@ -1567,11 +1559,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Constructor<?>[] getConstructors() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
return copyConstructors(privateGetDeclaredConstructors(true));
|
||||
}
|
||||
|
||||
@ -1625,12 +1615,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Field getField(String name)
|
||||
throws NoSuchFieldException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
Field field = getField0(name);
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(name);
|
||||
@ -1710,12 +1698,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Method getMethod(String name, Class<?>... parameterTypes)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
Method method = getMethod0(name, parameterTypes);
|
||||
if (method == null) {
|
||||
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
|
||||
@ -1764,12 +1750,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Constructor<T> getConstructor(Class<?>... parameterTypes)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
|
||||
return getConstructor0(parameterTypes, Member.PUBLIC);
|
||||
}
|
||||
|
||||
@ -1807,11 +1791,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Class<?>[] getDeclaredClasses() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
|
||||
return getDeclaredClasses0();
|
||||
}
|
||||
|
||||
@ -1851,11 +1833,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Field[] getDeclaredFields() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
return copyFields(privateGetDeclaredFields(false));
|
||||
}
|
||||
|
||||
@ -1899,11 +1879,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Method[] getDeclaredMethods() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
return copyMethods(privateGetDeclaredMethods(false));
|
||||
}
|
||||
|
||||
@ -1944,11 +1922,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
return copyConstructors(privateGetDeclaredConstructors(false));
|
||||
}
|
||||
|
||||
@ -1987,12 +1963,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Field getDeclaredField(String name)
|
||||
throws NoSuchFieldException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
Field field = searchFields(privateGetDeclaredFields(false), name);
|
||||
if (field == null) {
|
||||
throw new NoSuchFieldException(name);
|
||||
@ -2042,12 +2016,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
|
||||
if (method == null) {
|
||||
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
|
||||
@ -2092,12 +2064,10 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*
|
||||
* @since JDK1.1
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
// be very careful not to change the stack depth of this
|
||||
// checkMemberAccess call for security reasons
|
||||
// see java.lang.SecurityManager.checkMemberAccess
|
||||
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
|
||||
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
|
||||
return getConstructor0(parameterTypes, Member.DECLARED);
|
||||
}
|
||||
|
||||
@ -2255,23 +2225,40 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*/
|
||||
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,
|
||||
* 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
|
||||
* control.
|
||||
*/
|
||||
private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) {
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
|
||||
final SecurityManager s = System.getSecurityManager();
|
||||
if (s != null) {
|
||||
s.checkMemberAccess(this, which);
|
||||
ClassLoader cl = getClassLoader0();
|
||||
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
|
||||
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)) {
|
||||
String name = this.getName();
|
||||
int i = name.lastIndexOf('.');
|
||||
|
@ -55,6 +55,7 @@ import sun.misc.CompoundEnumeration;
|
||||
import sun.misc.Resource;
|
||||
import sun.misc.URLClassPath;
|
||||
import sun.misc.VM;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
@ -1159,11 +1160,6 @@ public abstract class ClassLoader {
|
||||
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>
|
||||
* The registration succeeds if and only if all of the following
|
||||
@ -1179,8 +1175,11 @@ public abstract class ClassLoader {
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@CallerSensitive
|
||||
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 {
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
@CallerSensitive
|
||||
public final ClassLoader getParent() {
|
||||
if (parent == null)
|
||||
return null;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = getCallerClassLoader();
|
||||
if (needsClassLoaderPermissionCheck(ccl, this)) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
checkClassLoaderPermission(this, Reflection.getCallerClass());
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
@ -1408,6 +1405,7 @@ public abstract class ClassLoader {
|
||||
*
|
||||
* @revised 1.4
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static ClassLoader getSystemClassLoader() {
|
||||
initSystemClassLoader();
|
||||
if (scl == null) {
|
||||
@ -1415,10 +1413,7 @@ public abstract class ClassLoader {
|
||||
}
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = getCallerClassLoader();
|
||||
if (needsClassLoaderPermissionCheck(ccl, scl)) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
checkClassLoaderPermission(scl, Reflection.getCallerClass());
|
||||
}
|
||||
return scl;
|
||||
}
|
||||
@ -1471,8 +1466,8 @@ public abstract class ClassLoader {
|
||||
// class loader 'from' is same as class loader 'to' or an ancestor
|
||||
// of 'to'. The class loader in a system domain can access
|
||||
// any class loader.
|
||||
static boolean needsClassLoaderPermissionCheck(ClassLoader from,
|
||||
ClassLoader to)
|
||||
private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
|
||||
ClassLoader to)
|
||||
{
|
||||
if (from == to)
|
||||
return false;
|
||||
@ -1483,13 +1478,8 @@ public abstract class ClassLoader {
|
||||
return !to.isAncestor(from);
|
||||
}
|
||||
|
||||
// Returns the invoker's class loader, or null if none.
|
||||
// NOTE: This must always be invoked when there is exactly one intervening
|
||||
// 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);
|
||||
// Returns the class's class loader, or null if none.
|
||||
static ClassLoader getClassLoader(Class<?> caller) {
|
||||
// This can be null if the VM is requesting it
|
||||
if (caller == null) {
|
||||
return null;
|
||||
@ -1498,6 +1488,17 @@ public abstract class ClassLoader {
|
||||
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
|
||||
// @GuardedBy("ClassLoader.class")
|
||||
private static ClassLoader scl;
|
||||
|
@ -49,6 +49,8 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import sun.net.www.ParseUtil;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
@ -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
|
||||
* information is available from the archive or codebase.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Package getPackage(String name) {
|
||||
ClassLoader l = ClassLoader.getCallerClassLoader();
|
||||
ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
|
||||
if (l != null) {
|
||||
return l.getPackage(name);
|
||||
} else {
|
||||
@ -294,8 +297,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
|
||||
* @return a new array of packages known to the callers {@code ClassLoader}
|
||||
* instance. An zero length array is returned if none are known.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Package[] getPackages() {
|
||||
ClassLoader l = ClassLoader.getCallerClassLoader();
|
||||
ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
|
||||
if (l != null) {
|
||||
return l.getPackages();
|
||||
} else {
|
||||
|
@ -27,6 +27,8 @@ package java.lang;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.StringTokenizer;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* Every Java application has a single instance of class
|
||||
@ -790,8 +792,9 @@ public class Runtime {
|
||||
* @see java.lang.SecurityException
|
||||
* @see java.lang.SecurityManager#checkLink(java.lang.String)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void load(String filename) {
|
||||
load0(System.getCallerClass(), filename);
|
||||
load0(Reflection.getCallerClass(), filename);
|
||||
}
|
||||
|
||||
synchronized void load0(Class<?> fromClass, String filename) {
|
||||
@ -850,8 +853,9 @@ public class Runtime {
|
||||
* @see java.lang.SecurityException
|
||||
* @see java.lang.SecurityManager#checkLink(java.lang.String)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void loadLibrary(String libname) {
|
||||
loadLibrary0(System.getCallerClass(), libname);
|
||||
loadLibrary0(Reflection.getCallerClass(), libname);
|
||||
}
|
||||
|
||||
synchronized void loadLibrary0(Class<?> fromClass, String libname) {
|
||||
|
@ -36,10 +36,10 @@ import java.net.SocketPermission;
|
||||
import java.net.NetPermission;
|
||||
import java.util.Hashtable;
|
||||
import java.net.InetAddress;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.URL;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
/**
|
||||
@ -1679,6 +1679,7 @@ class SecurityManager {
|
||||
* @since JDK1.1
|
||||
* @see #checkPermission(java.security.Permission) checkPermission
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void checkMemberAccess(Class<?> clazz, int which) {
|
||||
if (clazz == null) {
|
||||
throw new NullPointerException("class can't be null");
|
||||
|
@ -35,6 +35,7 @@ import java.security.AllPermission;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import sun.nio.ch.Interruptible;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import sun.reflect.annotation.AnnotationType;
|
||||
@ -1072,8 +1073,9 @@ public final class System {
|
||||
* @see java.lang.Runtime#load(java.lang.String)
|
||||
* @see java.lang.SecurityManager#checkLink(java.lang.String)
|
||||
*/
|
||||
@CallerSensitive
|
||||
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 {
|
||||
* @see java.lang.Runtime#loadLibrary(java.lang.String)
|
||||
* @see java.lang.SecurityManager#checkLink(java.lang.String)
|
||||
*/
|
||||
@CallerSensitive
|
||||
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 {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 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;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import sun.nio.ch.Interruptible;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
|
||||
@ -1443,15 +1445,14 @@ class Thread implements Runnable {
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
@CallerSensitive
|
||||
public ClassLoader getContextClassLoader() {
|
||||
if (contextClassLoader == null)
|
||||
return null;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = ClassLoader.getCallerClassLoader();
|
||||
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
ClassLoader.checkClassLoaderPermission(contextClassLoader,
|
||||
Reflection.getCallerClass());
|
||||
}
|
||||
return contextClassLoader;
|
||||
}
|
||||
|
@ -709,7 +709,9 @@ import jdk.internal.org.objectweb.asm.Type;
|
||||
InvokerBytecodeGenerator.maybeDump(className, classFile);
|
||||
Class<? extends BoundMethodHandle> bmhClass =
|
||||
//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);
|
||||
|
||||
return bmhClass;
|
||||
|
@ -391,10 +391,11 @@ import java.util.Objects;
|
||||
|
||||
// private flags, not part of RECOGNIZED_MODIFIERS:
|
||||
static final int
|
||||
IS_METHOD = MN_IS_METHOD, // method (not constructor)
|
||||
IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
|
||||
IS_FIELD = MN_IS_FIELD, // field
|
||||
IS_TYPE = MN_IS_TYPE; // nested type
|
||||
IS_METHOD = MN_IS_METHOD, // method (not constructor)
|
||||
IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
|
||||
IS_FIELD = MN_IS_FIELD, // field
|
||||
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_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
|
||||
@ -430,6 +431,10 @@ import java.util.Objects;
|
||||
public boolean isPackage() {
|
||||
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. */
|
||||
public boolean isAccessibleFrom(Class<?> lookupClass) {
|
||||
|
@ -34,6 +34,8 @@ import sun.invoke.empty.Empty;
|
||||
import sun.invoke.util.ValueConversions;
|
||||
import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import static java.lang.invoke.LambdaForm.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
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) {
|
||||
final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected
|
||||
Class<?> actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG);
|
||||
// This method is called via MH_checkCallerClass and so it's
|
||||
// correct to ask for the immediate caller here.
|
||||
Class<?> actual = Reflection.getCallerClass();
|
||||
if (actual != expected && actual != expected2)
|
||||
throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
|
||||
+(expected == expected2 ? "" : ", or else "+expected2.getName()));
|
||||
|
@ -26,7 +26,6 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
@ -34,7 +33,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* @author jrose
|
||||
*/
|
||||
@ -101,6 +100,7 @@ class MethodHandleNatives {
|
||||
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
|
||||
MN_IS_FIELD = 0x00040000, // field
|
||||
MN_IS_TYPE = 0x00080000, // nested type
|
||||
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
|
||||
MN_REFERENCE_KIND_SHIFT = 24, // refKind
|
||||
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:
|
||||
@ -391,129 +391,24 @@ class MethodHandleNatives {
|
||||
* I.e., does it call Reflection.getCallerClass or a similer method
|
||||
* to ask about the identity of its caller?
|
||||
*/
|
||||
// FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive.
|
||||
static boolean isCallerSensitive(MemberName mem) {
|
||||
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();
|
||||
switch (mem.getName()) {
|
||||
case "doPrivileged":
|
||||
case "doPrivilegedWithCombiner":
|
||||
return defc == java.security.AccessController.class;
|
||||
case "checkMemberAccess":
|
||||
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":
|
||||
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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
|
||||
if (symbolicRefClass == definingClass) return true;
|
||||
|
@ -30,6 +30,7 @@ import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.invoke.WrapperInstance;
|
||||
import java.util.ArrayList;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
@ -137,14 +138,14 @@ public class MethodHandleProxies {
|
||||
// entry points, must be covered by hand-written or automatically
|
||||
// generated adapter classes.
|
||||
//
|
||||
@CallerSensitive
|
||||
public static
|
||||
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
|
||||
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
|
||||
throw new IllegalArgumentException("not a public interface: "+intfc.getName());
|
||||
final MethodHandle mh;
|
||||
if (System.getSecurityManager() != null) {
|
||||
final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
|
||||
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
|
||||
final Class<?> caller = Reflection.getCallerClass();
|
||||
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
|
||||
ReflectUtil.checkProxyPackageAccess(ccl, intfc);
|
||||
mh = ccl != null ? bindCaller(target, caller) : target;
|
||||
|
@ -26,13 +26,17 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import sun.invoke.util.ValueConversions;
|
||||
import sun.invoke.util.VerifyAccess;
|
||||
import sun.invoke.util.Wrapper;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
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.security.util.SecurityConstants;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
|
||||
@ -65,8 +69,9 @@ public class MethodHandles {
|
||||
* 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.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Lookup lookup() {
|
||||
return new Lookup();
|
||||
return new Lookup(Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -416,18 +421,11 @@ public class MethodHandles {
|
||||
* for method handle creation.
|
||||
* Must be called by from a method 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) {
|
||||
this(lookupClass, ALL_MODES);
|
||||
// make sure we haven't accidentally picked up a privileged class:
|
||||
checkUnprivilegedlookupClass(lookupClass);
|
||||
}
|
||||
|
||||
private Lookup(Class<?> lookupClass, int allowedModes) {
|
||||
@ -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.
|
||||
* The type of the method handle will be that of the method.
|
||||
@ -594,12 +578,14 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public
|
||||
MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||
MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
return getDirectMethod(REF_invokeStatic, refc, method, callerClass);
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
checkSecurityManager(refc, method, callerClass);
|
||||
return getDirectMethod(REF_invokeStatic, refc, method,
|
||||
findBoundCallerClass(method, callerClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -645,6 +631,7 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||
if (refc == MethodHandle.class) {
|
||||
MethodHandle mh = findVirtualForMH(name, type);
|
||||
@ -652,9 +639,10 @@ public class MethodHandles {
|
||||
}
|
||||
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
|
||||
MemberName method = resolveOrFail(refKind, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
Class<?> callerClass = findBoundCallerClass(method);
|
||||
return getDirectMethod(refKind, refc, method, callerClass);
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
checkSecurityManager(refc, method, callerClass);
|
||||
return getDirectMethod(refKind, refc, method,
|
||||
findBoundCallerClass(method, callerClass));
|
||||
}
|
||||
private MethodHandle findVirtualForMH(String name, MethodType type) {
|
||||
// these names require special lookups because of the implicit MethodType argument
|
||||
@ -691,10 +679,11 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||
String name = "<init>";
|
||||
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);
|
||||
}
|
||||
|
||||
@ -732,14 +721,16 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
|
||||
Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
|
||||
checkSpecialCaller(specialCaller);
|
||||
Lookup specialLookup = this.in(specialCaller);
|
||||
MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
Class<?> callerClass = findBoundCallerClass(method);
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass);
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
checkSecurityManager(refc, method, callerClass);
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method,
|
||||
findBoundCallerClass(method, callerClass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -759,9 +750,10 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -782,9 +774,10 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -804,9 +797,10 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -826,9 +820,10 @@ public class MethodHandles {
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -878,12 +873,14 @@ return mh1;
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||
Class<? extends Object> refc = receiver.getClass(); // may get NPE
|
||||
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
|
||||
checkSecurityManager(refc, method); // stack walk magic: do not refactor
|
||||
Class<?> callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor
|
||||
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass);
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
checkSecurityManager(refc, method, callerClass);
|
||||
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method,
|
||||
findBoundCallerClass(method, callerClass));
|
||||
return mh.bindReceiver(receiver).setVarargs(method);
|
||||
}
|
||||
|
||||
@ -908,13 +905,14 @@ return mh1;
|
||||
* is set and {@code asVarargsCollector} fails
|
||||
* @throws NullPointerException if the argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle unreflect(Method m) throws IllegalAccessException {
|
||||
MemberName method = new MemberName(m);
|
||||
byte refKind = method.getReferenceKind();
|
||||
if (refKind == REF_invokeSpecial)
|
||||
refKind = REF_invokeVirtual;
|
||||
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;
|
||||
return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass);
|
||||
}
|
||||
@ -940,12 +938,13 @@ return mh1;
|
||||
* is set and {@code asVarargsCollector} fails
|
||||
* @throws NullPointerException if any argument is null
|
||||
*/
|
||||
@CallerSensitive
|
||||
public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
|
||||
checkSpecialCaller(specialCaller);
|
||||
Lookup specialLookup = this.in(specialCaller);
|
||||
MemberName method = new MemberName(m, true);
|
||||
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
|
||||
return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass);
|
||||
}
|
||||
@ -1050,20 +1049,35 @@ return mh1;
|
||||
* 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).
|
||||
* 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;
|
||||
if (MethodHandleNatives.isCallerSensitive(m)) {
|
||||
// Do not refactor this to a more "logical" place, since it is stack walk magic.
|
||||
// Note that this is the same expression as in Step 2 below in checkSecurityManager.
|
||||
callerClass = ((allowedModes & PRIVATE) != 0
|
||||
? lookupClass // for strong access modes, no extra check
|
||||
// next line does stack walk magic; do not refactor:
|
||||
: getCallerClassAtEntryPoint(true));
|
||||
: callerAtEntryPoint);
|
||||
}
|
||||
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>.
|
||||
* Determines a trustable caller class to compare with refc, the symbolic reference class.
|
||||
@ -1071,46 +1085,55 @@ return mh1;
|
||||
* 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.
|
||||
*/
|
||||
void checkSecurityManager(Class<?> refc, MemberName m) {
|
||||
void checkSecurityManager(Class<?> refc, MemberName m, Class<?> caller) {
|
||||
SecurityManager smgr = System.getSecurityManager();
|
||||
if (smgr == null) return;
|
||||
if (allowedModes == TRUSTED) return;
|
||||
|
||||
final boolean overridden = isCheckMemberAccessOverridden(smgr);
|
||||
// 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:
|
||||
Class<?> callerClass = ((allowedModes & PRIVATE) != 0
|
||||
? lookupClass // for strong access modes, no extra check
|
||||
// next line does stack walk magic; do not refactor:
|
||||
: getCallerClassAtEntryPoint(true));
|
||||
: caller);
|
||||
if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) ||
|
||||
(callerClass != lookupClass &&
|
||||
!VerifyAccess.classLoaderIsAncestor(callerClass, refc)))
|
||||
smgr.checkPackageAccess(VerifyAccess.getPackageName(refc));
|
||||
|
||||
// Step 3:
|
||||
if (m.isPublic()) return;
|
||||
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:
|
||||
if (defc != refc)
|
||||
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 {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.reflect;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.ConstructorAccessor;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.generics.repository.ConstructorRepository;
|
||||
@ -392,14 +393,14 @@ public final class Constructor<T> extends Executable {
|
||||
* @exception ExceptionInInitializerError if the initialization provoked
|
||||
* by this method fails.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public T newInstance(Object ... initargs)
|
||||
throws InstantiationException, IllegalAccessException,
|
||||
IllegalArgumentException, InvocationTargetException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass(2);
|
||||
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, null, modifiers);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.reflect;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.FieldAccessor;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.generics.repository.FieldRepository;
|
||||
@ -376,9 +377,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* @exception ExceptionInInitializerError if the initialization provoked
|
||||
* by this method fails.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Object get(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).get(obj);
|
||||
}
|
||||
|
||||
@ -404,9 +412,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public boolean getBoolean(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getBoolean(obj);
|
||||
}
|
||||
|
||||
@ -432,9 +447,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public byte getByte(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getByte(obj);
|
||||
}
|
||||
|
||||
@ -462,9 +484,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public char getChar(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getChar(obj);
|
||||
}
|
||||
|
||||
@ -492,9 +521,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public short getShort(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getShort(obj);
|
||||
}
|
||||
|
||||
@ -522,9 +558,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public int getInt(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getInt(obj);
|
||||
}
|
||||
|
||||
@ -552,9 +595,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public long getLong(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getLong(obj);
|
||||
}
|
||||
|
||||
@ -582,9 +632,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public float getFloat(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getFloat(obj);
|
||||
}
|
||||
|
||||
@ -612,9 +669,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#get
|
||||
*/
|
||||
@CallerSensitive
|
||||
public double getDouble(Object obj)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
return getFieldAccessor(obj).getDouble(obj);
|
||||
}
|
||||
|
||||
@ -684,9 +748,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* @exception ExceptionInInitializerError if the initialization provoked
|
||||
* by this method fails.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void set(Object obj, Object value)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).set(obj, value);
|
||||
}
|
||||
|
||||
@ -714,9 +785,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setBoolean(Object obj, boolean z)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setBoolean(obj, z);
|
||||
}
|
||||
|
||||
@ -744,9 +822,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setByte(Object obj, byte b)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setByte(obj, b);
|
||||
}
|
||||
|
||||
@ -774,9 +859,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setChar(Object obj, char c)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setChar(obj, c);
|
||||
}
|
||||
|
||||
@ -804,9 +896,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setShort(Object obj, short s)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setShort(obj, s);
|
||||
}
|
||||
|
||||
@ -834,9 +933,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setInt(Object obj, int i)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setInt(obj, i);
|
||||
}
|
||||
|
||||
@ -864,9 +970,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setLong(Object obj, long l)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setLong(obj, l);
|
||||
}
|
||||
|
||||
@ -894,9 +1007,16 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setFloat(Object obj, float f)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setFloat(obj, f);
|
||||
}
|
||||
|
||||
@ -924,20 +1044,26 @@ class Field extends AccessibleObject implements Member {
|
||||
* by this method fails.
|
||||
* @see Field#set
|
||||
*/
|
||||
@CallerSensitive
|
||||
public void setDouble(Object obj, double d)
|
||||
throws IllegalArgumentException, IllegalAccessException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
getFieldAccessor(obj).setDouble(obj, d);
|
||||
}
|
||||
|
||||
// Convenience routine which performs security checks
|
||||
// security check is done before calling this method
|
||||
private FieldAccessor getFieldAccessor(Object obj)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
doSecurityCheck(obj);
|
||||
boolean ov = override;
|
||||
FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor;
|
||||
return (a != null)? a : acquireFieldAccessor(ov);
|
||||
FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
|
||||
return (a != null) ? a : acquireFieldAccessor(ov);
|
||||
}
|
||||
|
||||
// NOTE that there is no synchronization used here. It is correct
|
||||
@ -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}
|
||||
* @since 1.5
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.reflect;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.MethodAccessor;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.generics.repository.MethodRepository;
|
||||
@ -472,14 +473,14 @@ public final class Method extends Executable {
|
||||
* @exception ExceptionInInitializerError if the initialization
|
||||
* provoked by this method fails.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public Object invoke(Object obj, Object... args)
|
||||
throws IllegalAccessException, IllegalArgumentException,
|
||||
InvocationTargetException
|
||||
{
|
||||
if (!override) {
|
||||
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
|
||||
Class<?> caller = Reflection.getCallerClass(1);
|
||||
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
checkAccess(caller, clazz, obj, modifiers);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
import sun.misc.ProxyGenerator;
|
||||
import sun.misc.VM;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.security.util.SecurityConstants;
|
||||
@ -408,28 +410,21 @@ public class Proxy implements java.io.Serializable {
|
||||
* @throws NullPointerException if the {@code interfaces} array
|
||||
* argument or any of its elements are {@code null}
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Class<?> getProxyClass(ClassLoader loader,
|
||||
Class<?>... interfaces)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
|
||||
}
|
||||
|
||||
private static void checkProxyLoader(ClassLoader ccl,
|
||||
ClassLoader loader)
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
if (loader == null && ccl != null) {
|
||||
if (!ProxyAccessHelper.allowNullLoader) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
}
|
||||
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
|
||||
}
|
||||
|
||||
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
|
||||
* Class.forName (VM will invoke ClassLoader.checkPackageAccess):
|
||||
@ -446,17 +441,28 @@ public class Proxy implements java.io.Serializable {
|
||||
* will throw IllegalAccessError when the generated proxy class is
|
||||
* being defined via the defineClass0 method.
|
||||
*/
|
||||
private static Class<?> getProxyClass0(ClassLoader loader,
|
||||
Class<?>... interfaces) {
|
||||
private static void checkProxyAccess(Class<?> caller,
|
||||
ClassLoader loader,
|
||||
Class<?>... interfaces)
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
|
||||
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
|
||||
final ClassLoader ccl = caller.getClassLoader();
|
||||
checkProxyLoader(ccl, loader);
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
|
||||
if (!ProxyAccessHelper.allowNullLoader) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
throw new IllegalArgumentException("interface limit exceeded");
|
||||
}
|
||||
@ -698,6 +704,7 @@ public class Proxy implements java.io.Serializable {
|
||||
* if the invocation handler, {@code h}, is
|
||||
* {@code null}
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Object newProxyInstance(ClassLoader loader,
|
||||
Class<?>[] interfaces,
|
||||
InvocationHandler h)
|
||||
@ -707,10 +714,15 @@ public class Proxy implements java.io.Serializable {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
final SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -718,7 +730,6 @@ public class Proxy implements java.io.Serializable {
|
||||
try {
|
||||
final Constructor<?> cons = cl.getConstructor(constructorParams);
|
||||
final InvocationHandler ih = h;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
|
||||
// create proxy instance with doPrivilege as the proxy class may
|
||||
// implement non-public interfaces that requires a special permission
|
||||
|
@ -26,6 +26,8 @@
|
||||
package java.security;
|
||||
|
||||
import sun.security.util.Debug;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* <p> The AccessController class is used for access control operations
|
||||
@ -264,6 +266,7 @@ public final class AccessController {
|
||||
* @see java.security.DomainCombiner
|
||||
*/
|
||||
|
||||
@CallerSensitive
|
||||
public static native <T> T doPrivileged(PrivilegedAction<T> action);
|
||||
|
||||
/**
|
||||
@ -288,14 +291,15 @@ public final class AccessController {
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
|
||||
|
||||
AccessControlContext acc = getStackAccessControlContext();
|
||||
if (acc == null) {
|
||||
return AccessController.doPrivileged(action);
|
||||
}
|
||||
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 {
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T doPrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context);
|
||||
|
||||
@ -353,6 +358,7 @@ public final class AccessController {
|
||||
* @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
|
||||
* @see java.security.DomainCombiner
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T
|
||||
doPrivileged(PrivilegedExceptionAction<T> action)
|
||||
throws PrivilegedActionException;
|
||||
@ -383,34 +389,29 @@ public final class AccessController {
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public static <T> T doPrivilegedWithCombiner
|
||||
(PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
|
||||
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)
|
||||
throws PrivilegedActionException
|
||||
{
|
||||
AccessControlContext acc = getStackAccessControlContext();
|
||||
if (acc == null) {
|
||||
return AccessController.doPrivileged(action);
|
||||
}
|
||||
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
|
||||
*/
|
||||
private static AccessControlContext preserveCombiner
|
||||
(DomainCombiner combiner) {
|
||||
|
||||
/**
|
||||
* callerClass[0] = Reflection.getCallerClass
|
||||
* callerClass[1] = AccessController.preserveCombiner
|
||||
* callerClass[2] = AccessController.doPrivileged
|
||||
* callerClass[3] = caller
|
||||
*/
|
||||
final Class<?> callerClass = sun.reflect.Reflection.getCallerClass(3);
|
||||
private static AccessControlContext preserveCombiner(DomainCombiner combiner,
|
||||
Class<?> caller)
|
||||
{
|
||||
ProtectionDomain callerPd = doPrivileged
|
||||
(new PrivilegedAction<ProtectionDomain>() {
|
||||
public ProtectionDomain run() {
|
||||
return callerClass.getProtectionDomain();
|
||||
return caller.getProtectionDomain();
|
||||
}
|
||||
});
|
||||
|
||||
@ -455,6 +456,7 @@ public final class AccessController {
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T
|
||||
doPrivileged(PrivilegedExceptionAction<T> action,
|
||||
AccessControlContext context)
|
||||
|
@ -30,6 +30,7 @@ import java.util.ServiceLoader;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
|
||||
@ -192,14 +193,11 @@ public class DriverManager {
|
||||
* has been exceeded and has at least tried to cancel the
|
||||
* current database connection attempt
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Connection getConnection(String url,
|
||||
java.util.Properties info) throws SQLException {
|
||||
|
||||
// Gets the classloader of the code that called this method, may
|
||||
// be null.
|
||||
ClassLoader callerCL = DriverManager.getCallerClassLoader();
|
||||
|
||||
return (getConnection(url, info, callerCL));
|
||||
return (getConnection(url, info, Reflection.getCallerClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,14 +224,11 @@ public class DriverManager {
|
||||
* has been exceeded and has at least tried to cancel the
|
||||
* current database connection attempt
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Connection getConnection(String url,
|
||||
String user, String password) throws SQLException {
|
||||
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) {
|
||||
info.put("user", user);
|
||||
}
|
||||
@ -241,7 +236,7 @@ public class DriverManager {
|
||||
info.put("password", password);
|
||||
}
|
||||
|
||||
return (getConnection(url, info, callerCL));
|
||||
return (getConnection(url, info, Reflection.getCallerClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,16 +254,12 @@ public class DriverManager {
|
||||
* has been exceeded and has at least tried to cancel the
|
||||
* current database connection attempt
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Connection getConnection(String url)
|
||||
throws SQLException {
|
||||
|
||||
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();
|
||||
|
||||
return (getConnection(url, info, callerCL));
|
||||
return (getConnection(url, info, Reflection.getCallerClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,21 +273,20 @@ public class DriverManager {
|
||||
* that can connect to the given URL
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Driver getDriver(String url)
|
||||
throws SQLException {
|
||||
|
||||
println("DriverManager.getDriver(\"" + url + "\")");
|
||||
|
||||
// Gets the classloader of the code that called this method, may
|
||||
// be null.
|
||||
ClassLoader callerCL = DriverManager.getCallerClassLoader();
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
|
||||
// Walk through the loaded registeredDrivers attempting to locate someone
|
||||
// who understands the given URL.
|
||||
for (DriverInfo aDriver : registeredDrivers) {
|
||||
// If the caller does not have permission to load the driver then
|
||||
// skip it.
|
||||
if(isDriverAllowed(aDriver.driver, callerCL)) {
|
||||
if(isDriverAllowed(aDriver.driver, callerClass)) {
|
||||
try {
|
||||
if(aDriver.driver.acceptsURL(url)) {
|
||||
// Success!
|
||||
@ -350,20 +340,18 @@ public class DriverManager {
|
||||
* @param driver the JDBC Driver to drop
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static synchronized void deregisterDriver(Driver driver)
|
||||
throws SQLException {
|
||||
if (driver == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gets the classloader of the code that called this method,
|
||||
// may be null.
|
||||
ClassLoader callerCL = DriverManager.getCallerClassLoader();
|
||||
println("DriverManager.deregisterDriver: " + driver);
|
||||
|
||||
DriverInfo aDriver = new DriverInfo(driver);
|
||||
if(registeredDrivers.contains(aDriver)) {
|
||||
if (isDriverAllowed(driver, callerCL)) {
|
||||
if (isDriverAllowed(driver, Reflection.getCallerClass())) {
|
||||
registeredDrivers.remove(aDriver);
|
||||
} else {
|
||||
// If the caller does not have permission to load the driver then
|
||||
@ -384,18 +372,17 @@ public class DriverManager {
|
||||
*
|
||||
* @return the list of JDBC Drivers loaded by the caller's class loader
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static java.util.Enumeration<Driver> getDrivers() {
|
||||
java.util.Vector<Driver> result = new java.util.Vector<>();
|
||||
|
||||
// Gets the classloader of the code that called this method, may
|
||||
// be null.
|
||||
ClassLoader callerCL = DriverManager.getCallerClassLoader();
|
||||
Class<?> callerClass = Reflection.getCallerClass();
|
||||
|
||||
// Walk through the loaded registeredDrivers.
|
||||
for(DriverInfo aDriver : registeredDrivers) {
|
||||
// If the caller does not have permission to load the driver then
|
||||
// skip it.
|
||||
if(isDriverAllowed(aDriver.driver, callerCL)) {
|
||||
if(isDriverAllowed(aDriver.driver, callerClass)) {
|
||||
result.addElement(aDriver.driver);
|
||||
} else {
|
||||
println(" skipping: " + aDriver.getClass().getName());
|
||||
@ -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
|
||||
// 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) {
|
||||
boolean result = false;
|
||||
if(driver != null) {
|
||||
@ -586,18 +569,19 @@ public class DriverManager {
|
||||
|
||||
// Worker method called by the public getConnection() methods.
|
||||
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
|
||||
* (which is invoking this class indirectly)
|
||||
* classloader, so that the JDBC driver class outside rt.jar
|
||||
* can be loaded from here.
|
||||
*/
|
||||
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
|
||||
synchronized(DriverManager.class) {
|
||||
// synchronize loading of the correct classloader.
|
||||
if(callerCL == null) {
|
||||
callerCL = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
// synchronize loading of the correct classloader.
|
||||
if (callerCL == null) {
|
||||
callerCL = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
if(url == null) {
|
||||
|
@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.spi.ResourceBundleControlProvider;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.util.locale.BaseLocale;
|
||||
import sun.util.locale.LocaleObjectCache;
|
||||
|
||||
@ -440,14 +442,10 @@ public abstract class ResourceBundle {
|
||||
|
||||
/*
|
||||
* Automatic determination of the ClassLoader to be used to load
|
||||
* resources on behalf of the client. N.B. The client is getLoader's
|
||||
* caller's caller.
|
||||
* resources on behalf of the client.
|
||||
*/
|
||||
private static ClassLoader getLoader() {
|
||||
Class<?>[] stack = getClassContext();
|
||||
/* Magic number 2 identifies our caller's caller */
|
||||
Class<?> c = stack[2];
|
||||
ClassLoader cl = (c == null) ? null : c.getClassLoader();
|
||||
private static ClassLoader getLoader(Class<?> caller) {
|
||||
ClassLoader cl = caller == null ? null : caller.getClassLoader();
|
||||
if (cl == null) {
|
||||
// When the caller's loader is the boot class loader, cl is null
|
||||
// here. In that case, ClassLoader.getSystemClassLoader() may
|
||||
@ -461,8 +459,6 @@ public abstract class ResourceBundle {
|
||||
return cl;
|
||||
}
|
||||
|
||||
private static native Class<?>[] getClassContext();
|
||||
|
||||
/**
|
||||
* A wrapper of ClassLoader.getSystemClassLoader().
|
||||
*/
|
||||
@ -746,11 +742,11 @@ public abstract class ResourceBundle {
|
||||
* 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
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static final ResourceBundle getBundle(String baseName)
|
||||
{
|
||||
return getBundleImpl(baseName, Locale.getDefault(),
|
||||
/* must determine loader here, else we break stack invariant */
|
||||
getLoader(),
|
||||
getLoader(Reflection.getCallerClass()),
|
||||
getDefaultControl(baseName));
|
||||
}
|
||||
|
||||
@ -788,11 +784,11 @@ public abstract class ResourceBundle {
|
||||
* needed.
|
||||
* @since 1.6
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static final ResourceBundle getBundle(String baseName,
|
||||
Control control) {
|
||||
return getBundleImpl(baseName, Locale.getDefault(),
|
||||
/* must determine loader here, else we break stack invariant */
|
||||
getLoader(),
|
||||
getLoader(Reflection.getCallerClass()),
|
||||
control);
|
||||
}
|
||||
|
||||
@ -817,12 +813,12 @@ public abstract class ResourceBundle {
|
||||
* if no resource bundle for the specified base name can be found
|
||||
* @return a resource bundle for the given base name and locale
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static final ResourceBundle getBundle(String baseName,
|
||||
Locale locale)
|
||||
{
|
||||
return getBundleImpl(baseName, locale,
|
||||
/* must determine loader here, else we break stack invariant */
|
||||
getLoader(),
|
||||
getLoader(Reflection.getCallerClass()),
|
||||
getDefaultControl(baseName));
|
||||
}
|
||||
|
||||
@ -863,11 +859,11 @@ public abstract class ResourceBundle {
|
||||
* needed.
|
||||
* @since 1.6
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
|
||||
Control control) {
|
||||
return getBundleImpl(baseName, targetLocale,
|
||||
/* must determine loader here, else we break stack invariant */
|
||||
getLoader(),
|
||||
getLoader(Reflection.getCallerClass()),
|
||||
control);
|
||||
}
|
||||
|
||||
@ -1721,8 +1717,9 @@ public abstract class ResourceBundle {
|
||||
* @since 1.6
|
||||
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static final void clearCache() {
|
||||
clearCache(getLoader());
|
||||
clearCache(getLoader(Reflection.getCallerClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
@ -77,8 +80,9 @@ public abstract class AtomicIntegerFieldUpdater<T> {
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
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> {
|
||||
private final Class<T> tclass;
|
||||
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 Class<?> caller;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
@ -376,7 +382,6 @@ public abstract class AtomicIntegerFieldUpdater<T> {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
caller = sun.reflect.Reflection.getCallerClass(3);
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
|
@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
@ -77,11 +80,13 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
|
||||
return new CASUpdater<U>(tclass, fieldName);
|
||||
return new CASUpdater<U>(tclass, fieldName, caller);
|
||||
else
|
||||
return new LockedUpdater<U>(tclass, fieldName);
|
||||
return new LockedUpdater<U>(tclass, fieldName, caller);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,9 +370,8 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
private final Class<T> tclass;
|
||||
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 Class<?> caller;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
@ -376,7 +380,6 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
caller = sun.reflect.Reflection.getCallerClass(3);
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
@ -490,9 +493,8 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
private final Class<T> tclass;
|
||||
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;
|
||||
Class<?> caller = null;
|
||||
int modifiers = 0;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
@ -501,7 +503,6 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
caller = sun.reflect.Reflection.getCallerClass(3);
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
|
@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.function.BinaryOperator;
|
||||
import sun.misc.Unsafe;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
@ -96,10 +99,12 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
|
||||
* or the field is inaccessible to the caller according to Java language
|
||||
* access control
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
|
||||
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
|
||||
vclass,
|
||||
fieldName);
|
||||
fieldName,
|
||||
Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,10 +302,11 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
|
||||
|
||||
AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
|
||||
Class<V> vclass,
|
||||
final String fieldName) {
|
||||
final String fieldName,
|
||||
final Class<?> caller)
|
||||
{
|
||||
final Field field;
|
||||
final Class<?> fieldClass;
|
||||
final Class<?> caller;
|
||||
final int modifiers;
|
||||
try {
|
||||
field = AccessController.doPrivileged(
|
||||
@ -309,7 +315,6 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
|
||||
return tclass.getDeclaredField(fieldName);
|
||||
}
|
||||
});
|
||||
caller = sun.reflect.Reflection.getCallerClass(3);
|
||||
modifiers = field.getModifiers();
|
||||
sun.reflect.misc.ReflectUtil.ensureMemberAccess(
|
||||
caller, tclass, null, modifiers);
|
||||
|
@ -36,6 +36,8 @@ import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Supplier;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
/**
|
||||
* A Logger object is used to log messages for a specific
|
||||
@ -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();
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
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) {
|
||||
return manager.demandSystemLogger(name, resourceBundleName);
|
||||
}
|
||||
@ -377,6 +376,7 @@ public class Logger {
|
||||
|
||||
// Synchronization is not required here. All synchronization for
|
||||
// adding a new Logger object is handled by LogManager.addLogger().
|
||||
@CallerSensitive
|
||||
public static Logger getLogger(String name) {
|
||||
// This method is intentionally not a wrapper around a call
|
||||
// to getLogger(name, resourceBundleName). If it were then
|
||||
@ -388,7 +388,7 @@ public class Logger {
|
||||
// would throw an IllegalArgumentException in the second call
|
||||
// because the wrapper would result in an attempt to replace
|
||||
// the existing "resourceBundleForFoo" with null.
|
||||
return demandLogger(name, null);
|
||||
return demandLogger(name, null, Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -434,8 +434,9 @@ public class Logger {
|
||||
|
||||
// Synchronization is not required here. All synchronization for
|
||||
// adding a new Logger object is handled by LogManager.addLogger().
|
||||
@CallerSensitive
|
||||
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
|
||||
// thrown by setupResourceInfo().
|
||||
|
@ -28,6 +28,7 @@ import java.util.*;
|
||||
import java.security.*;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
@ -60,9 +61,10 @@ public class ScriptEngineManager {
|
||||
*
|
||||
* @see java.lang.Thread#getContextClassLoader
|
||||
*/
|
||||
@CallerSensitive
|
||||
public ScriptEngineManager() {
|
||||
ClassLoader ctxtLoader = Thread.currentThread().getContextClassLoader();
|
||||
if (canCallerAccessLoader(ctxtLoader)) {
|
||||
if (canCallerAccessLoader(ctxtLoader, Reflection.getCallerClass())) {
|
||||
if (DEBUG) System.out.println("using " + ctxtLoader);
|
||||
init(ctxtLoader);
|
||||
} else {
|
||||
@ -419,10 +421,10 @@ public class ScriptEngineManager {
|
||||
/** Global bindings associated with script engines created by this manager. */
|
||||
private Bindings globalScope;
|
||||
|
||||
private boolean canCallerAccessLoader(ClassLoader loader) {
|
||||
private boolean canCallerAccessLoader(ClassLoader loader, Class<?> caller) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader callerLoader = getCallerClassLoader();
|
||||
ClassLoader callerLoader = getClassLoader(caller);
|
||||
if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) {
|
||||
if (loader != callerLoader || !isAncestor(loader, callerLoader)) {
|
||||
try {
|
||||
@ -438,10 +440,9 @@ public class ScriptEngineManager {
|
||||
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.
|
||||
private ClassLoader getCallerClassLoader() {
|
||||
Class<?> caller = Reflection.getCallerClass(3);
|
||||
private ClassLoader getClassLoader(Class<?> caller) {
|
||||
if (caller == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ package sun.misc;
|
||||
import java.security.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import sun.reflect.CallerSensitive;
|
||||
import sun.reflect.Reflection;
|
||||
|
||||
|
||||
/**
|
||||
* A collection of methods for performing low-level, unsafe operations.
|
||||
@ -80,9 +83,10 @@ public final class Unsafe {
|
||||
* <code>checkPropertiesAccess</code> method doesn't allow
|
||||
* access to the system properties.
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static Unsafe getUnsafe() {
|
||||
Class<?> cc = sun.reflect.Reflection.getCallerClass(2);
|
||||
if (!VM.isSystemDomainLoader(cc.getClassLoader()))
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (!VM.isSystemDomainLoader(caller.getClassLoader()))
|
||||
throw new SecurityException("Unsafe");
|
||||
return theUnsafe;
|
||||
}
|
||||
@ -817,8 +821,6 @@ public final class Unsafe {
|
||||
ClassLoader loader,
|
||||
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.
|
||||
* <p>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,13 +23,19 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jvm.h"
|
||||
package sun.reflect;
|
||||
|
||||
#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)
|
||||
{
|
||||
return JVM_GetClassContext(env);
|
||||
/**
|
||||
* A method annotated @CallerSensitive is sensitive to its calling class,
|
||||
* via {@link sun.reflect.Reflection#getCallerClass Reflection.getCallerClass},
|
||||
* or via some equivalent.
|
||||
*
|
||||
* @author John R. Rose
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({CONSTRUCTOR, METHOD})
|
||||
public @interface CallerSensitive {
|
||||
}
|
@ -51,16 +51,11 @@ public class Reflection {
|
||||
methodFilterMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/** Returns the class of the method <code>realFramesToSkip</code>
|
||||
frames up the stack (zero-based), ignoring frames associated
|
||||
with java.lang.reflect.Method.invoke() and its implementation.
|
||||
The first frame is that associated with this method, so
|
||||
<code>getCallerClass(0)</code> returns the Class object for
|
||||
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);
|
||||
/** Returns the class of the caller of the method calling this method,
|
||||
ignoring frames associated with java.lang.reflect.Method.invoke()
|
||||
and its implementation. */
|
||||
@CallerSensitive
|
||||
public static native Class<?> getCallerClass();
|
||||
|
||||
/** Retrieves the access flags written to the class file. For
|
||||
inner classes these flags may differ from those returned by
|
||||
@ -321,4 +316,27 @@ public class Reflection {
|
||||
}
|
||||
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);
|
||||
/*
|
||||
* java.lang.Class and java.lang.ClassLoader
|
||||
*/
|
||||
|
||||
#define JVM_DEPTH -1
|
||||
|
||||
/*
|
||||
* Returns the class in which the code invoking the native method
|
||||
* belongs.
|
||||
* Returns the immediate caller class of the native method invoking
|
||||
* 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.
|
||||
* In 1.2, they do. Therefore native methods like Class.forName
|
||||
* can no longer look at the current frame for the caller class.
|
||||
* The depth parameter must be -1 (JVM_DEPTH). The caller is expected
|
||||
* to be marked with sun.reflect.CallerSensitive. The JVM will throw
|
||||
* an error if it is not marked propertly.
|
||||
*/
|
||||
JNIEXPORT jclass JNICALL
|
||||
JVM_GetCallerClass(JNIEnv *env, int n);
|
||||
JVM_GetCallerClass(JNIEnv *env, int depth);
|
||||
|
||||
|
||||
/*
|
||||
* Find primitive classes
|
||||
|
@ -492,24 +492,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find
|
||||
(*env)->ReleaseStringUTFChars(env, name, cname);
|
||||
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
|
||||
* Method: findBuiltinLib
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "java_lang_SecurityManager.h"
|
||||
#include "java_lang_ClassLoader.h"
|
||||
#include "java_util_ResourceBundle.h"
|
||||
|
||||
/*
|
||||
* Make sure a security manager instance is initialized.
|
||||
|
@ -27,9 +27,9 @@
|
||||
#include "sun_reflect_Reflection.h"
|
||||
|
||||
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
|
||||
|
@ -478,7 +478,7 @@ jdk_io: $(call TestDirs, java/io)
|
||||
# Stable agentvm testruns (minus items from PROBLEM_LIST)
|
||||
JDK_ALL_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)
|
||||
|
||||
# Stable othervm testruns (minus items from PROBLEM_LIST)
|
||||
|
216
jdk/test/sun/reflect/CallerSensitive/CallerSensitiveFinder.java
Normal file
216
jdk/test/sun/reflect/CallerSensitive/CallerSensitiveFinder.java
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
201
jdk/test/sun/reflect/CallerSensitive/MethodFinder.java
Normal file
201
jdk/test/sun/reflect/CallerSensitive/MethodFinder.java
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
37
jdk/test/sun/reflect/Reflection/GetCallerClass.java
Normal file
37
jdk/test/sun/reflect/Reflection/GetCallerClass.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
113
jdk/test/sun/reflect/Reflection/GetCallerClassTest.java
Normal file
113
jdk/test/sun/reflect/Reflection/GetCallerClassTest.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
68
jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh
Normal file
68
jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh
Normal file
@ -0,0 +1,68 @@
|
||||
#
|
||||
# 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
|
Loading…
x
Reference in New Issue
Block a user