# HG changeset patch # User mchung # Date 1365176580 25200 # Node ID d03d07eea280c68aa2de23856e384385fe60df93 # Parent 52080db9cd975a6470c88f88170143db8812c31a 8011557: Improve reflection utility classes Reviewed-by: ahgross, alanb diff -r 52080db9cd97 -r d03d07eea280 src/share/classes/java/lang/Class.java --- a/src/share/classes/java/lang/Class.java Mon Apr 08 12:48:19 2013 -0700 +++ b/src/share/classes/java/lang/Class.java Fri Apr 05 08:43:00 2013 -0700 @@ -2209,7 +2209,7 @@ if (i != -1) { // skip the package access check on a proxy class in default proxy package String pkg = name.substring(0, i); - if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { + if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { s.checkPackageAccess(pkg); } } diff -r 52080db9cd97 -r d03d07eea280 src/share/classes/java/lang/reflect/Proxy.java --- a/src/share/classes/java/lang/reflect/Proxy.java Mon Apr 08 12:48:19 2013 -0700 +++ b/src/share/classes/java/lang/reflect/Proxy.java Fri Apr 05 08:43:00 2013 -0700 @@ -302,13 +302,11 @@ return false; } - if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { - // all proxy interfaces are public - return false; - } - for (Class intf : proxyClass.getInterfaces()) { - if (!Modifier.isPublic(intf.getModifiers())) { - return true; + if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { + for (Class intf : proxyClass.getInterfaces()) { + if (!Modifier.isPublic(intf.getModifiers())) { + return true; + } } } return false; diff -r 52080db9cd97 -r d03d07eea280 src/share/classes/sun/reflect/misc/ReflectUtil.java --- a/src/share/classes/sun/reflect/misc/ReflectUtil.java Mon Apr 08 12:48:19 2013 -0700 +++ b/src/share/classes/sun/reflect/misc/ReflectUtil.java Fri Apr 05 08:43:00 2013 -0700 @@ -27,6 +27,7 @@ package sun.reflect.misc; import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import sun.reflect.Reflection; public final class ReflectUtil { @@ -123,10 +124,26 @@ } - public static void checkPackageAccess(Class clazz) { + /** + * Checks package access on the given class. + * + * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements + * a non-public interface (i.e. may be in a non-restricted package), + * also check the package access on the proxy interfaces. + */ + public static void checkPackageAccess(Class clazz) { checkPackageAccess(clazz.getName()); + if (isNonPublicProxyClass(clazz)) { + checkProxyPackageAccess(clazz); + } } + /** + * Checks package access on the given classname. + * This method is typically called when the Class instance is not + * available and the caller attempts to load a class on behalf + * the true caller (application). + */ public static void checkPackageAccess(String name) { SecurityManager s = System.getSecurityManager(); if (s != null) { @@ -188,13 +205,30 @@ } /** + * Check package access on the proxy interfaces that the given proxy class + * implements. + * + * @param clazz Proxy class object + */ + public static void checkProxyPackageAccess(Class clazz) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + // check proxy interfaces if the given class is a proxy class + if (Proxy.isProxyClass(clazz)) { + for (Class intf : clazz.getInterfaces()) { + checkPackageAccess(intf); + } + } + } + } + + /** * Access check on the interfaces that a proxy class implements and throw - * {@code SecurityException} if it accesses a restricted package. + * {@code SecurityException} if it accesses a restricted package from + * the caller's class loader. * * @param ccl the caller's class loader * @param interfaces the list of interfaces that a proxy class implements - * - * @see Proxy#checkProxyAccess */ public static void checkProxyPackageAccess(ClassLoader ccl, Class... interfaces) @@ -211,4 +245,16 @@ } public static final String PROXY_PACKAGE = "com.sun.proxy"; + + /** + * Test if the given class is a proxy class that implements + * non-public interface. Such proxy class may be in a non-restricted + * package that bypasses checkPackageAccess. + */ + public static boolean isNonPublicProxyClass(Class cls) { + String name = cls.getName(); + int i = name.lastIndexOf('.'); + String pkg = (i != -1) ? name.substring(0, i) : ""; + return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); + } }