() {
+ 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} );
diff --git a/src/share/classes/java/lang/reflect/ReflectPermission.java b/src/share/classes/java/lang/reflect/ReflectPermission.java
index 635da52d8571e2f99ddf96e139111fb88d610976..6570e79224245a0e7e7737416b77ca1ad32ba5cc 100644
--- a/src/share/classes/java/lang/reflect/ReflectPermission.java
+++ b/src/share/classes/java/lang/reflect/ReflectPermission.java
@@ -26,12 +26,7 @@
package java.lang.reflect;
/**
- * The Permission class for reflective operations. A
- * ReflectPermission is a named permission 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.
*
* The following table
* provides a summary description of what the permission allows,
@@ -47,11 +42,21 @@ package java.lang.reflect;
*
*
* suppressAccessChecks |
- * 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. |
+ * 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. |
* This is dangerous in that information (possibly confidential) and
- * methods normally unavailable would be accessible to malicious code. |
+ * methods normally unavailable would be accessible to malicious code.
+ *
+ *
+ * newProxyInPackage.{package name} |
+ * ability to create a proxy instance in the specified package of which
+ * the non-public interface that the proxy class implements. |
+ * 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. |
*
*
*
@@ -63,6 +68,7 @@ package java.lang.reflect;
* @see Field#set
* @see Method#invoke
* @see Constructor#newInstance
+ * @see Proxy#newProxyInstance
*
* @since 1.2
*/
diff --git a/src/share/classes/java/util/DoubleSummaryStatistics.java b/src/share/classes/java/util/DoubleSummaryStatistics.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb79c56660b5ed3d129b88311e7db8e5d5e98d1e
--- /dev/null
+++ b/src/share/classes/java/util/DoubleSummaryStatistics.java
@@ -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.
+ *
+ * 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:
+ *
{@code
+ * DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new,
+ * DoubleSummaryStatistics::accept,
+ * DoubleSummaryStatistics::combine);
+ * }
+ *
+ * {@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:
+ *
+ *
{@code
+ * DoubleSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toDoubleSummaryStatistics(Person::getWeight));
+ *}
+ *
+ * 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());
+ }
+}
diff --git a/src/share/classes/java/util/IntSummaryStatistics.java b/src/share/classes/java/util/IntSummaryStatistics.java
new file mode 100644
index 0000000000000000000000000000000000000000..f179e67478ba4c2fa0ac710673f4b51df7ecee5e
--- /dev/null
+++ b/src/share/classes/java/util/IntSummaryStatistics.java
@@ -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.
+ *
+ * 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:
+ *
{@code
+ * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new,
+ * IntSummaryStatistics::accept,
+ * IntSummaryStatistics::combine);
+ * }
+ *
+ * {@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:
+ *
+ *
{@code
+ * IntSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toIntSummaryStatistics(Person::getDependents));
+ *}
+ *
+ * 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.
+ *
+ * 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());
+ }
+}
diff --git a/src/share/classes/java/util/LongSummaryStatistics.java b/src/share/classes/java/util/LongSummaryStatistics.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c7b7aee5610a2156908c202132350137892fd0c
--- /dev/null
+++ b/src/share/classes/java/util/LongSummaryStatistics.java
@@ -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.
+ *
+ *
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:
+ *
{@code
+ * LongSummaryStatistics stats = longStream.collect(LongSummaryStatistics::new,
+ * LongSummaryStatistics::accept,
+ * LongSummaryStatistics::combine);
+ * }
+ *
+ * {@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:
+ *
+ *
{@code
+ * LongSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toLongSummaryStatistics(Person::getAge));
+ *}
+ *
+ * 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.
+ *
+ * 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());
+ }
+}
diff --git a/src/share/classes/sun/misc/ProxyGenerator.java b/src/share/classes/sun/misc/ProxyGenerator.java
index 752553419f412f6620998e33eacb1025578c0459..dd93aa092e0c4b84892d67577ea11f95193401fb 100644
--- a/src/share/classes/sun/misc/ProxyGenerator.java
+++ b/src/share/classes/sun/misc/ProxyGenerator.java
@@ -27,11 +27,14 @@ package sun.misc;
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 @@ public class ProxyGenerator {
"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 @@ public class ProxyGenerator {
new java.security.PrivilegedAction() {
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 @@ public class ProxyGenerator {
/** 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 fields = new ArrayList();
+ private List fields = new ArrayList<>();
/** MethodInfo struct for each method of generated class */
- private List methods = new ArrayList();
+ private List methods = new ArrayList<>();
/**
* maps method signature string to list of ProxyMethod objects for
* proxy methods with that signature
*/
- private Map> proxyMethods =
- new HashMap>();
+ private Map> proxyMethods = new HashMap<>();
/** count of ProxyMethod objects added to proxyMethods */
private int proxyMethodCount = 0;
@@ -390,9 +414,10 @@ public class ProxyGenerator {
* 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 @@ public class ProxyGenerator {
* 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 @@ public class ProxyGenerator {
*/
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 @@ public class ProxyGenerator {
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 @@ public class ProxyGenerator {
// 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 @@ public class ProxyGenerator {
* compatibly with the throws clauses of both
* overridden methods.
*/
- List> legalExceptions = new ArrayList>();
+ List> legalExceptions = new ArrayList<>();
collectCompatibleTypes(
exceptionTypes, pm.exceptionTypes, legalExceptions);
collectCompatibleTypes(
@@ -588,7 +612,7 @@ public class ProxyGenerator {
}
}
} else {
- sigmethods = new ArrayList(3);
+ sigmethods = new ArrayList<>(3);
proxyMethods.put(sig, sigmethods);
}
sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
@@ -618,7 +642,7 @@ public class ProxyGenerator {
* List of return types that are not yet known to be
* assignable from ("covered" by) any of the others.
*/
- LinkedList> uncoveredReturnTypes = new LinkedList>();
+ LinkedList> uncoveredReturnTypes = new LinkedList<>();
nextNewReturnType:
for (ProxyMethod pm : methods) {
@@ -833,8 +857,8 @@ public class ProxyGenerator {
// 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 @@ public class ProxyGenerator {
Class>[] with,
List> 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 @@ public class ProxyGenerator {
* need to be caught.
*/
private static List> computeUniqueCatchList(Class>[] exceptions) {
- List> uniqueList = new ArrayList>();
+ List> 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,
diff --git a/src/share/classes/sun/reflect/annotation/AnnotationParser.java b/src/share/classes/sun/reflect/annotation/AnnotationParser.java
index a980a9126ef3bf1f85120730c01e58fecd0c0a11..ae15f249464bcb2c112c5511ff5350fd814f537d 100644
--- a/src/share/classes/sun/reflect/annotation/AnnotationParser.java
+++ b/src/share/classes/sun/reflect/annotation/AnnotationParser.java
@@ -30,6 +30,8 @@ import java.util.*;
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 @@ public class AnnotationParser {
* Returns an annotation of the given type backed by the given
* member -> value map.
*/
- public static Annotation annotationForMap(
- Class extends Annotation> type, Map memberValues)
+ public static Annotation annotationForMap(final Class extends Annotation> type,
+ final Map memberValues)
{
- return (Annotation) Proxy.newProxyInstance(
- type.getClassLoader(), new Class>[] { type },
- new AnnotationInvocationHandler(type, memberValues));
+ return AccessController.doPrivileged(new PrivilegedAction() {
+ public Annotation run() {
+ return (Annotation) Proxy.newProxyInstance(
+ type.getClassLoader(), new Class>[] { type },
+ new AnnotationInvocationHandler(type, memberValues));
+ }});
}
/**
diff --git a/src/share/classes/sun/rmi/server/Util.java b/src/share/classes/sun/rmi/server/Util.java
index 54f571175f8aa6eaaa3ee9956083ccc49fd76835..0f6c7ddee50ea6fb811d2203c828d6be672408cf 100644
--- a/src/share/classes/sun/rmi/server/Util.java
+++ b/src/share/classes/sun/rmi/server/Util.java
@@ -48,6 +48,7 @@ import java.security.AccessController;
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 @@ public final class Util {
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() {
+ public Remote run() {
+ return (Remote) Proxy.newProxyInstance(loader,
+ interfaces,
+ handler);
+ }});
} catch (IllegalArgumentException e) {
throw new StubNotFoundException("unable to create proxy", e);
}
diff --git a/src/share/classes/sun/tracing/ProviderSkeleton.java b/src/share/classes/sun/tracing/ProviderSkeleton.java
index 51a94472184b892d8a880f0cd42372aa2e33d1e2..ca5e58fbc6c0a67965fa66d91e4947345cc11080 100644
--- a/src/share/classes/sun/tracing/ProviderSkeleton.java
+++ b/src/share/classes/sun/tracing/ProviderSkeleton.java
@@ -130,8 +130,12 @@ public abstract class ProviderSkeleton implements InvocationHandler, Provider {
*/
@SuppressWarnings("unchecked")
public T newProxyInstance() {
- return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
- new Class>[] { providerType }, this);
+ final InvocationHandler ih = this;
+ return AccessController.doPrivileged(new PrivilegedAction() {
+ public T run() {
+ return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
+ new Class>[] { providerType }, ih);
+ }});
}
/**
diff --git a/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java b/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java
new file mode 100644
index 0000000000000000000000000000000000000000..62d1fde39f0172cc5a6c0422b5b178cb486260d5
--- /dev/null
+++ b/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java
@@ -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 perms = permissions.elements();
+ while (perms.hasMoreElements()) {
+ sb.append("\n").append(perms.nextElement().toString());
+ }
+ return sb.toString();
+ }
+ }
+}
diff --git a/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java b/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d4554fd77dfa4da43111b1d5a7553f34406b854
--- /dev/null
+++ b/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java
@@ -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;
+ }
+ });
+ }
+}
diff --git a/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java b/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
new file mode 100644
index 0000000000000000000000000000000000000000..86e96ba43d6ea0bdd619540a4e6d360c5d389025
--- /dev/null
+++ b/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
@@ -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 {
+}
diff --git a/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java b/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
new file mode 100644
index 0000000000000000000000000000000000000000..704a7ccdd5b6ca47a6b1ff1b0df67616d93e0190
--- /dev/null
+++ b/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
@@ -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 {
+}
diff --git a/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy b/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy
index 3ba44491acaa5a2bd72f3d3ba4f3cf5f359f5883..06773567405821b6ce1e7aa5ab12a43b3d63220a 100644
--- a/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy
+++ b/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy
@@ -16,6 +16,9 @@ grant {
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";