OpenJDK / jdk / jdk
changeset 16925:e42763b1ea55
Merge
author | coleenp |
---|---|
date | Wed, 17 Apr 2013 15:06:17 -0400 |
parents | 8a86b4fa429b 50bfa0defec2 |
children | 2fa9b0fd9dd6 |
files | |
diffstat | 14 files changed, 1076 insertions(+), 146 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 15:06:17 2013 -0400 @@ -28,7 +28,6 @@ import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.security.AccessController; -import java.security.Permission; import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; @@ -53,16 +52,14 @@ * <p>To create a proxy for some interface {@code Foo}: * <pre> * InvocationHandler handler = new MyInvocationHandler(...); - * Class proxyClass = Proxy.getProxyClass( - * Foo.class.getClassLoader(), new Class[] { Foo.class }); - * Foo f = (Foo) proxyClass. - * getConstructor(new Class[] { InvocationHandler.class }). - * newInstance(new Object[] { handler }); + * Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class); + * Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class). + * newInstance(handler); * </pre> * or more simply: * <pre> * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), - * new Class[] { Foo.class }, + * new Class<?>[] { Foo.class }, * handler); * </pre> * @@ -91,7 +88,11 @@ * <p>A proxy class has the following properties: * * <ul> - * <li>Proxy classes are public, final, and not abstract. + * <li>Proxy classes are <em>public, final, and not abstract</em> if + * all proxy interfaces are public.</li> + * + * <li>Proxy classes are <em>non-public, final, and not abstract</em> if + * any of the proxy interfaces is non-public.</li> * * <li>The unqualified name of a proxy class is unspecified. The space * of class names that begin with the string {@code "$Proxy"} @@ -273,76 +274,17 @@ * @param h the invocation handler for this proxy instance */ protected Proxy(InvocationHandler h) { - doNewInstanceCheck(); this.h = h; } - private static class ProxyAccessHelper { - // The permission is implementation specific. - static final Permission PROXY_PERMISSION = - new ReflectPermission("proxyConstructorNewInstance"); - // These system properties are defined to provide a short-term - // workaround if customers need to disable the new security checks. - static final boolean allowNewInstance; - static final boolean allowNullLoader; - static { - allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); - allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); - } - - private static boolean getBooleanProperty(final String key) { - String s = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty(key); - } - }); - return Boolean.valueOf(s); - } - - static boolean needsNewInstanceCheck(Class<?> proxyClass) { - if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { - 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; - } - } - return false; - } - } - - /* - * Access check on a proxy class that implements any non-public interface. - * - * @throws SecurityException if a security manager exists, and - * the caller does not have the permission. - */ - private void doNewInstanceCheck() { - SecurityManager sm = System.getSecurityManager(); - Class<?> proxyClass = this.getClass(); - if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { - try { - sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); - } catch (SecurityException e) { - throw new SecurityException("Not allowed to construct a Proxy " - + "instance that implements a non-public interface", e); - } - } - } - /** * Returns the {@code java.lang.Class} object for a proxy class * given a class loader and an array of interfaces. The proxy class * will be defined by the specified class loader and will implement - * all of the supplied interfaces. If a proxy class for the same - * permutation of interfaces has already been defined by the class - * loader, then the existing proxy class will be returned; otherwise, + * all of the supplied interfaces. If any of the given interfaces + * is non-public, the proxy class will be non-public. If a proxy class + * for the same permutation of interfaces has already been defined by the + * class loader, then the existing proxy class will be returned; otherwise, * a proxy class for those interfaces will be generated dynamically * and defined by the class loader. * @@ -407,6 +349,22 @@ * @throws IllegalArgumentException if any of the restrictions on the * parameters that may be passed to {@code getProxyClass} * are violated + * @throws SecurityException if a security manager, <em>s</em>, is present + * and any of the following conditions is met: + * <ul> + * <li> the given {@code loader} is {@code null} and + * the caller's class loader is not {@code null} and the + * invocation of {@link SecurityManager#checkPermission + * s.checkPermission} with + * {@code RuntimePermission("getClassLoader")} permission + * denies access.</li> + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to any one of the + * given proxy interfaces.</li> + * </ul> + * @throws NullPointerException if the {@code interfaces} array * argument or any of its elements are {@code null} */ @@ -449,9 +407,7 @@ if (sm != null) { ClassLoader ccl = caller.getClassLoader(); if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) { - if (!ProxyAccessHelper.allowNullLoader) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } ReflectUtil.checkProxyPackageAccess(ccl, interfaces); } @@ -593,6 +549,7 @@ try { String proxyPkg = null; // package to define proxy class in + int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* * Record the package of a non-public proxy interface so that the @@ -602,6 +559,7 @@ for (int i = 0; i < interfaces.length; i++) { int flags = interfaces[i].getModifiers(); if (!Modifier.isPublic(flags)) { + accessFlags = Modifier.FINAL; String name = interfaces[i].getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); @@ -637,7 +595,7 @@ * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( - proxyName, interfaces); + proxyName, interfaces, accessFlags); try { proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); @@ -678,12 +636,7 @@ /** * Returns an instance of a proxy class for the specified interfaces * that dispatches method invocations to the specified invocation - * handler. This method is equivalent to: - * <pre> - * Proxy.getProxyClass(loader, interfaces). - * getConstructor(new Class[] { InvocationHandler.class }). - * newInstance(new Object[] { handler }); - * </pre> + * handler. * * <p>{@code Proxy.newProxyInstance} throws * {@code IllegalArgumentException} for the same reasons that @@ -699,6 +652,27 @@ * @throws IllegalArgumentException if any of the restrictions on the * parameters that may be passed to {@code getProxyClass} * are violated + * @throws SecurityException if a security manager, <em>s</em>, is present + * and any of the following conditions is met: + * <ul> + * <li> the given {@code loader} is {@code null} and + * the caller's class loader is not {@code null} and the + * invocation of {@link SecurityManager#checkPermission + * s.checkPermission} with + * {@code RuntimePermission("getClassLoader")} permission + * denies access;</li> + * <li> the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to any one of the + * given proxy interfaces.</li> + * <li> any of the given proxy interfaces is non-public and the + * caller class is not in the same {@linkplain Package runtime package} + * as the non-public interface and the invocation of + * {@link SecurityManager#checkPermission s.checkPermission} with + * {@code ReflectPermission("newProxyInPackage.{package name}")} + * permission denies access.</li> + * </ul> * @throws NullPointerException if the {@code interfaces} array * argument or any of its elements are {@code null}, or * if the invocation handler, {@code h}, is @@ -728,24 +702,61 @@ * Invoke its constructor with the designated invocation handler. */ try { + if (sm != null) { + checkNewProxyPermission(Reflection.getCallerClass(), cl); + } + final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; - 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 - return AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - return newInstance(cons, ih); + if (!Modifier.isPublic(cl.getModifiers())) { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + cons.setAccessible(true); + return null; } }); + } + return cons.newInstance(new Object[]{h}); + } catch (IllegalAccessException|InstantiationException e) { + throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; } else { - return newInstance(cons, ih); + throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } + private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + String pcn = proxyClass.getName(); + if (pcn.startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { + // all proxy interfaces are public + return; + } + + ClassLoader ccl = caller.getClassLoader(); + ClassLoader pcl = proxyClass.getClassLoader(); + + // do permission check if the caller is in a different runtime package + // of the proxy class + int n = pcn.lastIndexOf('.'); + String pkg = (n == -1) ? "" : pcn.substring(0, n); + + n = caller.getName().lastIndexOf('.'); + String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); + + if (pcl != ccl || !pkg.equals(callerPkg)) { + sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); + } + } + } + private static Object newInstance(Constructor<?> cons, InvocationHandler h) { try { return cons.newInstance(new Object[] {h} );
--- a/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java Wed Apr 17 15:06:17 2013 -0400 @@ -26,12 +26,7 @@ package java.lang.reflect; /** - * The Permission class for reflective operations. A - * ReflectPermission is a <em>named permission</em> and has no - * actions. The only name currently defined is {@code suppressAccessChecks}, - * which allows suppressing the standard Java language access checks - * -- for public, default (package) access, protected, and private - * members -- performed by reflected objects at their point of use. + * The Permission class for reflective operations. * <P> * The following table * provides a summary description of what the permission allows, @@ -47,11 +42,21 @@ * * <tr> * <td>suppressAccessChecks</td> - * <td>ability to access - * fields and invoke methods in a class. Note that this includes - * not only public, but protected and private fields and methods as well.</td> + * <td>ability to suppress the standard Java language access checks + * on fields and methods in a class; allow access not only public members + * but also allow access to default (package) access, protected, + * and private members.</td> * <td>This is dangerous in that information (possibly confidential) and - * methods normally unavailable would be accessible to malicious code.</td> + * methods normally unavailable would be accessible to malicious code.</td> + * </tr> + * <tr> + * <td>newProxyInPackage.{package name}</td> + * <td>ability to create a proxy instance in the specified package of which + * the non-public interface that the proxy class implements.</td> + * <td>This gives code access to classes in packages to which it normally + * does not have access and the dynamic proxy class is in the system + * protection domain. Malicious code may use these classes to + * help in its attempt to compromise security in the system.</td> * </tr> * * </table> @@ -63,6 +68,7 @@ * @see Field#set * @see Method#invoke * @see Constructor#newInstance + * @see Proxy#newProxyInstance * * @since 1.2 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/DoubleSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.util; + +import java.util.function.DoubleConsumer; + +/** + * A state object for collecting statistics such as count, min, max, sum, and + * average. + * + * <p>This class is designed to work with (though does not require) + * {@linkplain java.util.stream streams}. For example, you can compute + * summary statistics on a stream of doubles with: + * <pre> {@code + * DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new, + * DoubleSummaryStatistics::accept, + * DoubleSummaryStatistics::combine); + * }</pre> + * + * <p>{@code DoubleSummaryStatistics} can be used as a + * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * target for a {@linkplain java.util.stream.Stream stream}. For example: + * + * <pre> {@code + * DoubleSummaryStatistics stats = people.stream() + * .collect(Collectors.toDoubleSummaryStatistics(Person::getWeight)); + *}</pre> + * + * This computes, in a single pass, the count of people, as well as the minimum, + * maximum, sum, and average of their weights. + * + * @implNote This implementation is not thread safe. However, it is safe to use + * {@link java.util.stream.Collectors#toDoubleSummaryStatistics(java.util.function.ToDoubleFunction) + * Collectors.toDoubleStatistics()} on a parallel stream, because the parallel + * implementation of {@link java.util.stream.Stream#collect Stream.collect()} + * provides the necessary partitioning, isolation, and merging of results for + * safe and efficient parallel execution. + * @since 1.8 + */ +public class DoubleSummaryStatistics implements DoubleConsumer { + private long count; + private double sum; + private double min = Double.POSITIVE_INFINITY; + private double max = Double.NEGATIVE_INFINITY; + + /** + * Construct an empty instance with zero count, zero sum, + * {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY} + * max and zero average. + */ + public DoubleSummaryStatistics() { } + + /** + * Records another value into the summary information. + * + * @param value the input value + */ + @Override + public void accept(double value) { + ++count; + sum += value; + min = Math.min(min, value); + max = Math.max(max, value); + } + + /** + * Combines the state of another {@code DoubleSummaryStatistics} into this + * one. + * + * @param other another {@code DoubleSummaryStatistics} + * @throws NullPointerException if {@code other} is null + */ + public void combine(DoubleSummaryStatistics other) { + count += other.count; + sum += other.sum; + min = Math.min(min, other.min); + max = Math.max(max, other.max); + } + + /** + * Return the count of values recorded. + * + * @return the count of values + */ + public final long getCount() { + return count; + } + + /** + * Returns the sum of values recorded, or zero if no values have been + * recorded. The sum returned can vary depending upon the order in which + * values are recorded. This is due to accumulated rounding error in + * addition of values of differing magnitudes. Values sorted by increasing + * absolute magnitude tend to yield more accurate results. If any recorded + * value is a {@code NaN} or the sum is at any point a {@code NaN} then the + * sum will be {@code NaN}. + * + * @return the sum of values, or zero if none + */ + public final double getSum() { + return sum; + } + + /** + * Returns the minimum recorded value, {@code Double.NaN} if any recorded + * value was NaN or {@code Double.POSITIVE_INFINITY} if no values were + * recorded. Unlike the numerical comparison operators, this method + * considers negative zero to be strictly smaller than positive zero. + * + * @return the minimum recorded value, {@code Double.NaN} if any recorded + * value was NaN or {@code Double.POSITIVE_INFINITY} if no values were + * recorded + */ + public final double getMin() { + return min; + } + + /** + * Returns the maximum recorded value, {@code Double.NaN} if any recorded + * value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were + * recorded. Unlike the numerical comparison operators, this method + * considers negative zero to be strictly smaller than positive zero. + * + * @return the maximum recorded value, {@code Double.NaN} if any recorded + * value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were + * recorded + */ + public final double getMax() { + return max; + } + + /** + * Returns the average of values recorded, or zero if no values have been + * recorded. The average returned can vary depending upon the order in + * which values are recorded. This is due to accumulated rounding error in + * addition of values of differing magnitudes. Values sorted by increasing + * absolute magnitude tend to yield more accurate results. If any recorded + * value is a {@code NaN} or the sum is at any point a {@code NaN} then the + * average will be {@code NaN}. + * + * @return the average of values, or zero if none + */ + public final double getAverage() { + return getCount() > 0 ? getSum() / getCount() : 0.0d; + } + + /** + * {@inheritDoc} + * + * Returns a non-empty string representation of this object suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + */ + @Override + public String toString() { + return String.format( + "%s{count=%d, sum=%f, min=%f, average=%f, max=%f}", + this.getClass().getSimpleName(), + getCount(), + getSum(), + getMin(), + getAverage(), + getMax()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/IntSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.util; + +import java.util.function.IntConsumer; + +/** + * A state object for collecting statistics such as count, min, max, sum, and + * average. + * + * <p>This class is designed to work with (though does not require) + * {@linkplain java.util.stream streams}. For example, you can compute + * summary statistics on a stream of ints with: + * <pre> {@code + * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new, + * IntSummaryStatistics::accept, + * IntSummaryStatistics::combine); + * }</pre> + * + * <p>{@code IntSummaryStatistics} can be used as a + * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * target for a {@linkplain java.util.stream.Stream stream}. For example: + * + * <pre> {@code + * IntSummaryStatistics stats = people.stream() + * .collect(Collectors.toIntSummaryStatistics(Person::getDependents)); + *}</pre> + * + * This computes, in a single pass, the count of people, as well as the minimum, + * maximum, sum, and average of their number of dependents. + * + * @implNote This implementation is not thread safe. However, it is safe to use + * {@link java.util.stream.Collectors#toIntSummaryStatistics(java.util.function.ToIntFunction) + * Collectors.toIntStatistics()} on a parallel stream, because the parallel + * implementation of {@link java.util.stream.Stream#collect Stream.collect()} + * provides the necessary partitioning, isolation, and merging of results for + * safe and efficient parallel execution. + * + * <p>This implementation does not check for overflow of the sum. + * @since 1.8 + */ +public class IntSummaryStatistics implements IntConsumer { + private long count; + private long sum; + private int min = Integer.MAX_VALUE; + private int max = Integer.MIN_VALUE; + + /** + * Construct an empty instance with zero count, zero sum, + * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero + * average. + */ + public IntSummaryStatistics() { } + + /** + * Records a new value into the summary information + * + * @param value the input value + */ + @Override + public void accept(int value) { + ++count; + sum += value; + min = Math.min(min, value); + max = Math.max(max, value); + } + + /** + * Combines the state of another {@code IntSummaryStatistics} into this one. + * + * @param other another {@code IntSummaryStatistics} + * @throws NullPointerException if {@code other} is null + */ + public void combine(IntSummaryStatistics other) { + count += other.count; + sum += other.sum; + min = Math.min(min, other.min); + max = Math.max(max, other.max); + } + + /** + * Returns the count of values recorded. + * + * @return the count of values + */ + public final long getCount() { + return count; + } + + /** + * Returns the sum of values recorded, or zero if no values have been + * recorded. + * + * @return the sum of values, or zero if none + */ + public final long getSum() { + return sum; + } + + /** + * Returns the minimum value recorded, or {@code Integer.MAX_VALUE} if no + * values have been recorded. + * + * @return the minimum value, or {@code Integer.MAX_VALUE} if none + */ + public final int getMin() { + return min; + } + + /** + * Returns the maximum value recorded, or {@code Integer.MIN_VALUE} if no + * values have been recorded. + * + * @return the maximum value, or {@code Integer.MIN_VALUE} if none + */ + public final int getMax() { + return max; + } + + /** + * Returns the average of values recorded, or zero if no values have been + * recorded. + * + * @return the average of values, or zero if none + */ + public final double getAverage() { + return getCount() > 0 ? (double) getSum() / getCount() : 0.0d; + } + + @Override + /** + * {@inheritDoc} + * + * Returns a non-empty string representation of this object suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + */ + public String toString() { + return String.format( + "%s{count=%d, sum=%d, min=%d, average=%d, max=%d}", + this.getClass().getSimpleName(), + getCount(), + getSum(), + getMin(), + getAverage(), + getMax()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/LongSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 java.util; + +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +/** + * A state object for collecting statistics such as count, min, max, sum, and + * average. + * + * <p>This class is designed to work with (though does not require) + * {@linkplain java.util.stream streams}. For example, you can compute + * summary statistics on a stream of longs with: + * <pre> {@code + * LongSummaryStatistics stats = longStream.collect(LongSummaryStatistics::new, + * LongSummaryStatistics::accept, + * LongSummaryStatistics::combine); + * }</pre> + * + * <p>{@code LongSummaryStatistics} can be used as a + * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction} + * target for a {@linkplain java.util.stream.Stream stream}. For example: + * + * <pre> {@code + * LongSummaryStatistics stats = people.stream() + * .collect(Collectors.toLongSummaryStatistics(Person::getAge)); + *}</pre> + * + * This computes, in a single pass, the count of people, as well as the minimum, + * maximum, sum, and average of their ages in milliseconds. + * + * @implNote This implementation is not thread safe. However, it is safe to use + * {@link java.util.stream.Collectors#toLongSummaryStatistics(java.util.function.ToLongFunction) + * Collectors.toLongStatistics()} on a parallel stream, because the parallel + * implementation of {@link java.util.stream.Stream#collect Stream.collect()} + * provides the necessary partitioning, isolation, and merging of results for + * safe and efficient parallel execution. + * + * <p>This implementation does not check for overflow of the sum. + * @since 1.8 + */ +public class LongSummaryStatistics implements LongConsumer, IntConsumer { + private long count; + private long sum; + private long min = Long.MAX_VALUE; + private long max = Long.MIN_VALUE; + + /** + * Construct an empty instance with zero count, zero sum, + * {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero + * average. + */ + public LongSummaryStatistics() { } + + /** + * Records a new {@code int} value into the summary information. + * + * @param value the input value + */ + @Override + public void accept(int value) { + accept((long) value); + } + + /** + * Records a new {@code long} value into the summary information. + * + * @param value the input value + */ + @Override + public void accept(long value) { + ++count; + sum += value; + min = Math.min(min, value); + max = Math.max(max, value); + } + + /** + * Combines the state of another {@code LongSummaryStatistics} into this + * one. + * + * @param other another {@code LongSummaryStatistics} + * @throws NullPointerException if {@code other} is null + */ + public void combine(LongSummaryStatistics other) { + count += other.count; + sum += other.sum; + min = Math.min(min, other.min); + max = Math.max(max, other.max); + } + + /** + * Returns the count of values recorded. + * + * @return the count of values + */ + public final long getCount() { + return count; + } + + /** + * Returns the sum of values recorded, or zero if no values have been + * recorded. + * + * @return the sum of values, or zero if none + */ + public final long getSum() { + return sum; + } + + /** + * Returns the minimum value recorded, or {@code Long.MAX_VALUE} if no + * values have been recorded. + * + * @return the minimum value, or {@code Long.MAX_VALUE} if none + */ + public final long getMin() { + return min; + } + + /** + * Returns the maximum value recorded, or {@code Long.MIN_VALUE} if no + * values have been recorded + * + * @return the maximum value, or {@code Long.MIN_VALUE} if none + */ + public final long getMax() { + return max; + } + + /** + * Returns the average of values recorded, or zero if no values have been + * recorded. + * + * @return The average of values, or zero if none + */ + public final double getAverage() { + return getCount() > 0 ? (double) getSum() / getCount() : 0.0d; + } + + @Override + /** + * {@inheritDoc} + * + * Returns a non-empty string representation of this object suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + */ + public String toString() { + return String.format( + "%s{count=%d, sum=%d, min=%d, average=%d, max=%d}", + this.getClass().getSimpleName(), + getCount(), + getSum(), + getMin(), + getAverage(), + getMax()); + } +}
--- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Apr 17 15:06:17 2013 -0400 @@ -27,11 +27,14 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.FileOutputStream; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; @@ -314,12 +317,25 @@ "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue(); /** - * Generate a proxy class given a name and a list of proxy interfaces. + * Generate a public proxy class given a name and a list of proxy interfaces. */ public static byte[] generateProxyClass(final String name, - Class[] interfaces) + Class<?>[] interfaces) { + return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER)); + } + + /** + * Generate a proxy class given a name and a list of proxy interfaces. + * + * @param name the class name of the proxy class + * @param interfaces proxy interfaces + * @param accessFlags access flags of the proxy class + */ + public static byte[] generateProxyClass(final String name, + Class<?>[] interfaces, + int accessFlags) { - ProxyGenerator gen = new ProxyGenerator(name, interfaces); + ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags); final byte[] classFile = gen.generateClassFile(); if (saveGeneratedFiles) { @@ -327,10 +343,16 @@ new java.security.PrivilegedAction<Void>() { public Void run() { try { - FileOutputStream file = - new FileOutputStream(dotToSlash(name) + ".class"); - file.write(classFile); - file.close(); + int i = name.lastIndexOf('.'); + Path path; + if (i > 0) { + Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar)); + Files.createDirectories(dir); + path = dir.resolve(name.substring(i+1, name.length()) + ".class"); + } else { + path = Paths.get(name + ".class"); + } + Files.write(path, classFile); return null; } catch (IOException e) { throw new InternalError( @@ -364,21 +386,23 @@ /** proxy interfaces */ private Class[] interfaces; + /** proxy class access flags */ + private int accessFlags; + /** constant pool of class being generated */ private ConstantPool cp = new ConstantPool(); /** FieldInfo struct for each field of generated class */ - private List<FieldInfo> fields = new ArrayList<FieldInfo>(); + private List<FieldInfo> fields = new ArrayList<>(); /** MethodInfo struct for each method of generated class */ - private List<MethodInfo> methods = new ArrayList<MethodInfo>(); + private List<MethodInfo> methods = new ArrayList<>(); /** * maps method signature string to list of ProxyMethod objects for * proxy methods with that signature */ - private Map<String, List<ProxyMethod>> proxyMethods = - new HashMap<String,List<ProxyMethod>>(); + private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>(); /** count of ProxyMethod objects added to proxyMethods */ private int proxyMethodCount = 0; @@ -390,9 +414,10 @@ * A ProxyGenerator object contains the state for the ongoing * generation of a particular proxy class. */ - private ProxyGenerator(String className, Class[] interfaces) { + private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) { this.className = className; this.interfaces = interfaces; + this.accessFlags = accessFlags; } /** @@ -422,10 +447,9 @@ * earlier interfaces precedence over later ones with duplicate * methods. */ - for (int i = 0; i < interfaces.length; i++) { - Method[] methods = interfaces[i].getMethods(); - for (int j = 0; j < methods.length; j++) { - addProxyMethod(methods[j], interfaces[i]); + for (Class<?> intf : interfaces) { + for (Method m : intf.getMethods()) { + addProxyMethod(m, intf); } } @@ -480,8 +504,8 @@ */ cp.getClass(dotToSlash(className)); cp.getClass(superclassName); - for (int i = 0; i < interfaces.length; i++) { - cp.getClass(dotToSlash(interfaces[i].getName())); + for (Class<?> intf: interfaces) { + cp.getClass(dotToSlash(intf.getName())); } /* @@ -508,7 +532,7 @@ cp.write(dout); // (write constant pool) // u2 access_flags; - dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER); + dout.writeShort(accessFlags); // u2 this_class; dout.writeShort(cp.getClass(dotToSlash(className))); // u2 super_class; @@ -517,9 +541,9 @@ // u2 interfaces_count; dout.writeShort(interfaces.length); // u2 interfaces[interfaces_count]; - for (int i = 0; i < interfaces.length; i++) { + for (Class<?> intf : interfaces) { dout.writeShort(cp.getClass( - dotToSlash(interfaces[i].getName()))); + dotToSlash(intf.getName()))); } // u2 fields_count; @@ -576,7 +600,7 @@ * compatibly with the throws clauses of both * overridden methods. */ - List<Class<?>> legalExceptions = new ArrayList<Class<?>>(); + List<Class<?>> legalExceptions = new ArrayList<>(); collectCompatibleTypes( exceptionTypes, pm.exceptionTypes, legalExceptions); collectCompatibleTypes( @@ -588,7 +612,7 @@ } } } else { - sigmethods = new ArrayList<ProxyMethod>(3); + sigmethods = new ArrayList<>(3); proxyMethods.put(sig, sigmethods); } sigmethods.add(new ProxyMethod(name, parameterTypes, returnType, @@ -618,7 +642,7 @@ * List of return types that are not yet known to be * assignable from ("covered" by) any of the others. */ - LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<Class<?>>(); + LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>(); nextNewReturnType: for (ProxyMethod pm : methods) { @@ -833,8 +857,8 @@ // u2 number_of_exceptions; out.writeShort(declaredExceptions.length); // u2 exception_index_table[number_of_exceptions]; - for (int i = 0; i < declaredExceptions.length; i++) { - out.writeShort(declaredExceptions[i]); + for (short value : declaredExceptions) { + out.writeShort(value); } } @@ -1525,11 +1549,11 @@ Class<?>[] with, List<Class<?>> list) { - for (int i = 0; i < from.length; i++) { - if (!list.contains(from[i])) { - for (int j = 0; j < with.length; j++) { - if (with[j].isAssignableFrom(from[i])) { - list.add(from[i]); + for (Class<?> fc: from) { + if (!list.contains(fc)) { + for (Class<?> wc: with) { + if (wc.isAssignableFrom(fc)) { + list.add(fc); break; } } @@ -1559,15 +1583,14 @@ * need to be caught. */ private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) { - List<Class<?>> uniqueList = new ArrayList<Class<?>>(); + List<Class<?>> uniqueList = new ArrayList<>(); // unique exceptions to catch uniqueList.add(Error.class); // always catch/rethrow these uniqueList.add(RuntimeException.class); nextException: - for (int i = 0; i < exceptions.length; i++) { - Class<?> ex = exceptions[i]; + for (Class<?> ex: exceptions) { if (ex.isAssignableFrom(Throwable.class)) { /* * If Throwable is declared to be thrown by the proxy method,
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Wed Apr 17 15:06:17 2013 -0400 @@ -30,6 +30,8 @@ import java.nio.ByteBuffer; import java.nio.BufferUnderflowException; import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.reflect.ConstantPool; import sun.reflect.generics.parser.SignatureParser; @@ -253,12 +255,15 @@ * Returns an annotation of the given type backed by the given * member -> value map. */ - public static Annotation annotationForMap( - Class<? extends Annotation> type, Map<String, Object> memberValues) + public static Annotation annotationForMap(final Class<? extends Annotation> type, + final Map<String, Object> memberValues) { - return (Annotation) Proxy.newProxyInstance( - type.getClassLoader(), new Class<?>[] { type }, - new AnnotationInvocationHandler(type, memberValues)); + return AccessController.doPrivileged(new PrivilegedAction<Annotation>() { + public Annotation run() { + return (Annotation) Proxy.newProxyInstance( + type.getClassLoader(), new Class<?>[] { type }, + new AnnotationInvocationHandler(type, memberValues)); + }}); } /**
--- a/jdk/src/share/classes/sun/rmi/server/Util.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/sun/rmi/server/Util.java Wed Apr 17 15:06:17 2013 -0400 @@ -48,6 +48,7 @@ import java.security.MessageDigest; import java.security.DigestOutputStream; import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.Map; @@ -140,17 +141,20 @@ return createStub(remoteClass, clientRef); } - ClassLoader loader = implClass.getClassLoader(); - Class[] interfaces = getRemoteInterfaces(implClass); - InvocationHandler handler = + final ClassLoader loader = implClass.getClassLoader(); + final Class[] interfaces = getRemoteInterfaces(implClass); + final InvocationHandler handler = new RemoteObjectInvocationHandler(clientRef); /* REMIND: private remote interfaces? */ try { - return (Remote) Proxy.newProxyInstance(loader, - interfaces, - handler); + return AccessController.doPrivileged(new PrivilegedAction<Remote>() { + public Remote run() { + return (Remote) Proxy.newProxyInstance(loader, + interfaces, + handler); + }}); } catch (IllegalArgumentException e) { throw new StubNotFoundException("unable to create proxy", e); }
--- a/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java Wed Apr 17 15:06:17 2013 -0400 @@ -130,8 +130,12 @@ */ @SuppressWarnings("unchecked") public <T extends Provider> T newProxyInstance() { - return (T)Proxy.newProxyInstance(providerType.getClassLoader(), - new Class<?>[] { providerType }, this); + final InvocationHandler ih = this; + return AccessController.doPrivileged(new PrivilegedAction<T>() { + public T run() { + return (T)Proxy.newProxyInstance(providerType.getClassLoader(), + new Class<?>[] { providerType }, ih); + }}); } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,215 @@ +/* + * 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.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; +import java.lang.reflect.ReflectPermission; +import java.security.AccessControlException; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.security.SecurityPermission; +import java.util.*; + +/* + * @test + * @bug 8004260 + * @summary Test proxy classes that implement non-public interface + * + * @build p.Foo + * @run main/othervm NonPublicProxyClass grant + * @run main/othervm NonPublicProxyClass deny + * @run main/othervm NonPublicProxyClass + */ +public class NonPublicProxyClass { + public interface PublicInterface { + void foo(); + } + interface NonPublicInterface { + void bar(); + } + + public static void main(String[] args) throws Exception { + ClassLoader loader = ClassLoader.getSystemClassLoader(); + Class<?> zipConstantsClass = Class.forName("java.util.zip.ZipConstants", false, null); + Class<?> fooClass = Class.forName("p.Foo"); + + NonPublicProxyClass test1 = + new NonPublicProxyClass(loader, PublicInterface.class, NonPublicInterface.class); + NonPublicProxyClass test2 = + new NonPublicProxyClass(loader, fooClass, PublicInterface.class); + NonPublicProxyClass test3 = + new NonPublicProxyClass(null, zipConstantsClass); + + if (args.length == 1) { + switch (args[0]) { + case "grant": Policy.setPolicy(new NewInstancePolicy(true)); + break; + case "deny" : Policy.setPolicy(new NewInstancePolicy(false)); + break; + default: throw new IllegalArgumentException(args[0]); + } + System.setSecurityManager(new SecurityManager()); + } + + test1.run(); + test2.run(); + test3.run(); + System.out.format("Test passed: security %s%n", + (args.length == 0 ? "manager not installed" : Policy.getPolicy())); + } + + private final ClassLoader loader; + private final Class<?>[] interfaces; + private final InvocationHandler handler = newInvocationHandler(); + private Class<?> proxyClass; + public NonPublicProxyClass(ClassLoader loader, Class<?> ... intfs) { + this.loader = loader; + this.interfaces = intfs; + } + + public void run() throws Exception { + boolean hasAccess = loader != null || hasAccess(); + try { + proxyClass = Proxy.getProxyClass(loader, interfaces); + if (!hasAccess) { + throw new RuntimeException("should have no permission to create proxy class"); + } + } catch (AccessControlException e) { + if (hasAccess) { + throw e; + } + if (e.getPermission().getClass() != RuntimePermission.class || + !e.getPermission().getName().equals("getClassLoader")) { + throw e; + } + return; + } + + if (Modifier.isPublic(proxyClass.getModifiers())) { + throw new RuntimeException(proxyClass + " must be non-public"); + } + newProxyInstance(); + newInstanceFromConstructor(proxyClass); + } + + private boolean hasAccess() { + if (System.getSecurityManager() == null) { + return true; + } + NewInstancePolicy policy = NewInstancePolicy.class.cast(Policy.getPolicy()); + return policy.grant; + } + + private final static String NEW_PROXY_IN_PKG = "newProxyInPackage."; + private void newProxyInstance() { + // expect newProxyInstance to succeed if it's in the same runtime package + int i = proxyClass.getName().lastIndexOf('.'); + String pkg = (i != -1) ? proxyClass.getName().substring(0, i) : ""; + boolean hasAccess = pkg.isEmpty() || hasAccess(); + try { + Proxy.newProxyInstance(loader, interfaces, handler); + if (!hasAccess) { + throw new RuntimeException("ERROR: Proxy.newProxyInstance should fail " + proxyClass); + } + } catch (AccessControlException e) { + if (hasAccess) { + throw e; + } + if (e.getPermission().getClass() != ReflectPermission.class || + !e.getPermission().getName().equals(NEW_PROXY_IN_PKG + pkg)) { + throw e; + } + } + } + + private void newInstanceFromConstructor(Class<?> proxyClass) + throws Exception + { + // expect newInstance to succeed if it's in the same runtime package + boolean isSamePackage = proxyClass.getName().lastIndexOf('.') == -1; + try { + Constructor cons = proxyClass.getConstructor(InvocationHandler.class); + cons.newInstance(newInvocationHandler()); + if (!isSamePackage) { + throw new RuntimeException("ERROR: Constructor.newInstance should not succeed"); + } + } catch (IllegalAccessException e) { + if (isSamePackage) { + throw e; + } + } + } + + private static InvocationHandler newInvocationHandler() { + return new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + Class<?>[] intfs = proxy.getClass().getInterfaces(); + System.out.println("Proxy for " + Arrays.toString(intfs) + + " " + method.getName() + " is being invoked"); + return null; + } + }; + } + + static class NewInstancePolicy extends Policy { + final PermissionCollection permissions = new Permissions(); + final boolean grant; + NewInstancePolicy(boolean grant) { + this.grant = grant; + permissions.add(new SecurityPermission("getPolicy")); + if (grant) { + permissions.add(new RuntimePermission("getClassLoader")); + permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "p")); + permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "java.util.zip")); + } + } + public PermissionCollection getPermissions(ProtectionDomain domain) { + return permissions; + } + + public PermissionCollection getPermissions(CodeSource codesource) { + return permissions; + } + + public boolean implies(ProtectionDomain domain, Permission perm) { + return permissions.implies(perm); + } + + public String toString() { + StringBuilder sb = new StringBuilder("policy: "); + Enumeration<Permission> perms = permissions.elements(); + while (perms.hasMoreElements()) { + sb.append("\n").append(perms.nextElement().toString()); + } + return sb.toString(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java Wed Apr 17 15:06:17 2013 -0400 @@ -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. + */ + +import java.lang.reflect.*; +import java.security.*; +import java.util.Arrays; + +/* + * @test + * @bug 8004260 + * @summary Test making a proxy instance that implements a non-public + * interface with and without security manager installed + * @build p.Foo p.Bar + * @run main SimpleProxy + */ +public class SimpleProxy { + public static void main(String[] args) throws Exception { + ClassLoader loader = SimpleProxy.class.getClassLoader(); + Class<?> fooClass = Class.forName("p.Foo"); + Class<?> barClass = Class.forName("p.Bar"); + + makeProxy(loader, fooClass); + + System.setSecurityManager(new SecurityManager()); + try { + makeProxy(loader, barClass); + throw new RuntimeException("should fail to new proxy instance of a non-public interface"); + } catch (AccessControlException e) { + if (e.getPermission().getClass() != ReflectPermission.class || + !e.getPermission().getName().equals("newProxyInPackage.p")) { + throw e; + } + } + } + + private static void makeProxy(ClassLoader loader, Class<?> cls) { + Class<?>[] intfs = new Class<?>[] { cls }; + Proxy.newProxyInstance(loader, intfs, new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + Class<?>[] intfs = proxy.getClass().getInterfaces(); + System.out.println("Proxy for " + Arrays.toString(intfs) + + " " + method.getName() + " is being invoked"); + return null; + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,26 @@ +/* + * 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 p; +interface Bar { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java Wed Apr 17 15:06:17 2013 -0400 @@ -0,0 +1,26 @@ +/* + * 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 p; +interface Foo { +}
--- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Wed Apr 17 12:50:45 2013 -0400 +++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Wed Apr 17 15:06:17 2013 -0400 @@ -16,6 +16,9 @@ permission java.lang.RuntimePermission "getClassLoader"; permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.lang.reflect.ReflectPermission "newProxyInPackage."; + permission java.lang.reflect.ReflectPermission "newProxyInPackage.java.util.zip"; + // used by TestLibrary to determine test environment permission java.util.PropertyPermission "test.classes", "read"; permission java.util.PropertyPermission "test.src", "read";