Merge
This commit is contained in:
commit
04d4410fb9
@ -28,7 +28,6 @@ package java.lang.reflect;
|
||||
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 @@ import sun.security.util.SecurityConstants;
|
||||
* <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 @@ import sun.security.util.SecurityConstants;
|
||||
* <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 @@ public class Proxy implements java.io.Serializable {
|
||||
* @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 @@ public class Proxy implements java.io.Serializable {
|
||||
* @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 @@ public class Proxy implements java.io.Serializable {
|
||||
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 @@ public class Proxy implements java.io.Serializable {
|
||||
|
||||
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 @@ public class Proxy implements java.io.Serializable {
|
||||
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 @@ public class Proxy implements java.io.Serializable {
|
||||
* 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 @@ public class Proxy implements java.io.Serializable {
|
||||
/**
|
||||
* 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 @@ public class Proxy implements java.io.Serializable {
|
||||
* @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 @@ public class Proxy implements java.io.Serializable {
|
||||
* 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} );
|
||||
|
@ -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 @@ package java.lang.reflect;
|
||||
*
|
||||
* <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 @@ package java.lang.reflect;
|
||||
* @see Field#set
|
||||
* @see Method#invoke
|
||||
* @see Constructor#newInstance
|
||||
* @see Proxy#newProxyInstance
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
|
187
jdk/src/share/classes/java/util/DoubleSummaryStatistics.java
Normal file
187
jdk/src/share/classes/java/util/DoubleSummaryStatistics.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
170
jdk/src/share/classes/java/util/IntSummaryStatistics.java
Normal file
170
jdk/src/share/classes/java/util/IntSummaryStatistics.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
182
jdk/src/share/classes/java/util/LongSummaryStatistics.java
Normal file
182
jdk/src/share/classes/java/util/LongSummaryStatistics.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
@ -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<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 @@ 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<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 @@ 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<Class<?>> legalExceptions = new ArrayList<Class<?>>();
|
||||
List<Class<?>> legalExceptions = new ArrayList<>();
|
||||
collectCompatibleTypes(
|
||||
exceptionTypes, pm.exceptionTypes, legalExceptions);
|
||||
collectCompatibleTypes(
|
||||
@ -588,7 +612,7 @@ public class ProxyGenerator {
|
||||
}
|
||||
}
|
||||
} 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 @@ public class ProxyGenerator {
|
||||
* 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 @@ 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<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 @@ public class ProxyGenerator {
|
||||
* 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,
|
||||
|
@ -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<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));
|
||||
}});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<Remote>() {
|
||||
public Remote run() {
|
||||
return (Remote) Proxy.newProxyInstance(loader,
|
||||
interfaces,
|
||||
handler);
|
||||
}});
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new StubNotFoundException("unable to create proxy", e);
|
||||
}
|
||||
|
@ -130,8 +130,12 @@ public abstract class ProviderSkeleton implements InvocationHandler, Provider {
|
||||
*/
|
||||
@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);
|
||||
}});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
26
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
Normal file
26
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
Normal file
@ -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 {
|
||||
}
|
26
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
Normal file
26
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
Normal file
@ -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 {
|
||||
}
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user