diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index ea47cca2fcaf4952a5b9e8c66d5f5b0ad3ad1f70..d400a6ac55d1d35dd265fcf75d7f00cf13377e5b 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2014, 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 @@ -256,8 +256,8 @@ public final class Class implements java.io.Serializable, @CallerSensitive public static Class forName(String className) throws ClassNotFoundException { - return forName0(className, true, - ClassLoader.getClassLoader(Reflection.getCallerClass())); + Class caller = Reflection.getCallerClass(); + return forName0(className, true, ClassLoader.getClassLoader(caller), caller); } @@ -327,22 +327,27 @@ public final class Class implements java.io.Serializable, ClassLoader loader) throws ClassNotFoundException { - if (sun.misc.VM.isSystemDomainLoader(loader)) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass()); + Class caller = null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Reflective call to get caller class is only needed if a security manager + // is present. Avoid the overhead of making this call otherwise. + caller = Reflection.getCallerClass(); + if (sun.misc.VM.isSystemDomainLoader(loader)) { + ClassLoader ccl = ClassLoader.getClassLoader(caller); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } - return forName0(name, initialize, loader); + return forName0(name, initialize, loader, caller); } - /** Called after security checks have been made. */ + /** Called after security check for system loader access checks have been made. */ private static native Class forName0(String name, boolean initialize, - ClassLoader loader) + ClassLoader loader, + Class caller) throws ClassNotFoundException; /** diff --git a/src/share/javavm/export/jvm.h b/src/share/javavm/export/jvm.h index ff5f823d8b536da9a9a6e1c82afc37d3a69be697..9426a16d454fe82a33b9e221817c07e68bd5c563 100644 --- a/src/share/javavm/export/jvm.h +++ b/src/share/javavm/export/jvm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -385,6 +385,19 @@ JVM_ResolveClass(JNIEnv *env, jclass cls); JNIEXPORT jclass JNICALL JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); +/* + * Find a class from a given class loader. Throws ClassNotFoundException. + * name: name of class + * init: whether initialization is done + * loader: class loader to look up the class. This may not be the same as the caller's + * class loader. + * caller: initiating class. The initiating class may be null when a security + * manager is not installed. + */ +JNIEXPORT jclass JNICALL +JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init, + jobject loader, jclass caller); + /* * Find a class from a given class loader. Throw ClassNotFoundException * or NoClassDefFoundError depending on the value of the last diff --git a/src/share/native/java/lang/Class.c b/src/share/native/java/lang/Class.c index b0ba34349d8d19ebcaffc1d77cfabd5e57c01124..2f5e6b5c8c29788e472479af0cdbda447c9bbfaa 100644 --- a/src/share/native/java/lang/Class.c +++ b/src/share/native/java/lang/Class.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2014, 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 @@ -97,7 +97,7 @@ Java_java_lang_Class_registerNatives(JNIEnv *env, jclass cls) JNIEXPORT jclass JNICALL Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname, - jboolean initialize, jobject loader) + jboolean initialize, jobject loader, jclass caller) { char *clname; jclass cls = 0; @@ -135,8 +135,7 @@ Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname, goto done; } - cls = JVM_FindClassFromClassLoader(env, clname, initialize, - loader, JNI_FALSE); + cls = JVM_FindClassFromCaller(env, clname, initialize, loader, caller); done: if (clname != buf) {