() {
+ public Void run() {
+ javaSecurityAccess.doIntersectionPrivilege(action, eventAcc);
+ return null;
+ }
+ }, stack, srcAcc);
+ }
+ }
+
+ private static AccessControlContext getAccessControlContextFrom(Object src) {
+ return src instanceof Component ?
+ ((Component)src).getAccessControlContext() :
+ src instanceof MenuComponent ?
+ ((MenuComponent)src).getAccessControlContext() :
+ src instanceof TrayIcon ?
+ ((TrayIcon)src).getAccessControlContext() :
+ null;
+ }
+
+ /**
+ * Called from dispatchEvent() under a correct AccessControlContext
+ */
+ private void dispatchEventImpl(final AWTEvent event, final Object src) {
event.isPosted = true;
- Object src = event.getSource();
if (event instanceof ActiveEvent) {
// This could become the sole method of dispatching in time.
setCurrentEventAndMostRecentTimeImpl(event);
-
((ActiveEvent)event).dispatch();
} else if (src instanceof Component) {
((Component)src).dispatchEvent(event);
diff --git a/jdk/src/share/classes/java/awt/LinearGradientPaint.java b/jdk/src/share/classes/java/awt/LinearGradientPaint.java
index 8d5d727540b..7a60c7d4b6c 100644
--- a/jdk/src/share/classes/java/awt/LinearGradientPaint.java
+++ b/jdk/src/share/classes/java/awt/LinearGradientPaint.java
@@ -57,8 +57,14 @@ import java.beans.ConstructorProperties;
*
*
*
- * The user may also select what action the {@code LinearGradientPaint}
- * should take when filling color outside the start and end points.
+ * The user may also select what action the {@code LinearGradientPaint} object
+ * takes when it is filling the space outside the start and end points by
+ * setting {@code CycleMethod} to either {@code REFLECTION} or {@code REPEAT}.
+ * The distances between any two colors in any of the reflected or repeated
+ * copies of the gradient are the same as the distance between those same two
+ * colors between the start and end points.
+ * Note that some minor variations in distances may occur due to sampling at
+ * the granularity of a pixel.
* If no cycle method is specified, {@code NO_CYCLE} will be chosen by
* default, which means the endpoint colors will be used to fill the
* remaining area.
diff --git a/jdk/src/share/classes/java/awt/MenuComponent.java b/jdk/src/share/classes/java/awt/MenuComponent.java
index 19d57394a23..d1a5a2577b4 100644
--- a/jdk/src/share/classes/java/awt/MenuComponent.java
+++ b/jdk/src/share/classes/java/awt/MenuComponent.java
@@ -33,6 +33,9 @@ import sun.awt.SunToolkit;
import sun.awt.AWTAccessor;
import javax.accessibility.*;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+
/**
* The abstract class MenuComponent is the superclass
* of all menu-related components. In this respect, the class
@@ -99,6 +102,23 @@ public abstract class MenuComponent implements java.io.Serializable {
*/
boolean newEventsOnly = false;
+ /*
+ * The menu's AccessControlContext.
+ */
+ private transient volatile AccessControlContext acc =
+ AccessController.getContext();
+
+ /*
+ * Returns the acc this menu component was constructed with.
+ */
+ final AccessControlContext getAccessControlContext() {
+ if (acc == null) {
+ throw new SecurityException(
+ "MenuComponent is missing AccessControlContext");
+ }
+ return acc;
+ }
+
/*
* Internal constants for serialization.
*/
@@ -402,6 +422,9 @@ public abstract class MenuComponent implements java.io.Serializable {
throws ClassNotFoundException, IOException, HeadlessException
{
GraphicsEnvironment.checkHeadless();
+
+ acc = AccessController.getContext();
+
s.defaultReadObject();
appContext = AppContext.getAppContext();
diff --git a/jdk/src/share/classes/java/awt/MultipleGradientPaint.java b/jdk/src/share/classes/java/awt/MultipleGradientPaint.java
index 598f68f6f03..0dfaf5071ae 100644
--- a/jdk/src/share/classes/java/awt/MultipleGradientPaint.java
+++ b/jdk/src/share/classes/java/awt/MultipleGradientPaint.java
@@ -286,6 +286,10 @@ public abstract class MultipleGradientPaint implements Paint {
/**
* Returns a copy of the transform applied to the gradient.
*
+ *
+ * Note that if no transform is applied to the gradient
+ * when it is created, the identity transform is used.
+ *
* @return a copy of the transform applied to the gradient
*/
public final AffineTransform getTransform() {
@@ -293,10 +297,12 @@ public abstract class MultipleGradientPaint implements Paint {
}
/**
- * Returns the transparency mode for this Paint object.
+ * Returns the transparency mode for this {@code Paint} object.
*
- * @return an integer value representing the transparency mode for
- * this Paint object
+ * @return {@code OPAQUE} if all colors used by this
+ * {@code Paint} object are opaque,
+ * {@code TRANSLUCENT} if at least one of the
+ * colors used by this {@code Paint} object is not opaque.
* @see java.awt.Transparency
*/
public final int getTransparency() {
diff --git a/jdk/src/share/classes/java/awt/RadialGradientPaint.java b/jdk/src/share/classes/java/awt/RadialGradientPaint.java
index d87a3253d46..ee99c32d9de 100644
--- a/jdk/src/share/classes/java/awt/RadialGradientPaint.java
+++ b/jdk/src/share/classes/java/awt/RadialGradientPaint.java
@@ -71,8 +71,24 @@ import java.beans.ConstructorProperties;
*
*
*
- * The user may also select what action the {@code RadialGradientPaint}
- * should take when filling color outside the bounds of the circle's radius.
+ * The user may also select what action the {@code RadialGradientPaint} object
+ * takes when it is filling the space outside the circle's radius by
+ * setting {@code CycleMethod} to either {@code REFLECTION} or {@code REPEAT}.
+ * The gradient color proportions are equal for any particular line drawn
+ * from the focus point. The following figure shows that the distance AB
+ * is equal to the distance BC, and the distance AD is equal to the distance DE.
+ *
+ *
+ *
+ * If the gradient and graphics rendering transforms are uniformly scaled and
+ * the user sets the focus so that it coincides with the center of the circle,
+ * the gradient color proportions are equal for any line drawn from the center.
+ * The following figure shows the distances AB, BC, AD, and DE. They are all equal.
+ *
+ *
+ *
+ * Note that some minor variations in distances may occur due to sampling at
+ * the granularity of a pixel.
* If no cycle method is specified, {@code NO_CYCLE} will be chosen by
* default, which means the the last keyframe color will be used to fill the
* remaining area.
@@ -604,7 +620,7 @@ public final class RadialGradientPaint extends MultipleGradientPaint {
}
/**
- * Returns a copy of the end point of the gradient axis.
+ * Returns a copy of the focus point of the radial gradient.
*
* @return a {@code Point2D} object that is a copy of the focus point
*/
diff --git a/jdk/src/share/classes/java/awt/TrayIcon.java b/jdk/src/share/classes/java/awt/TrayIcon.java
index 35a98706e7f..13185bf92fd 100644
--- a/jdk/src/share/classes/java/awt/TrayIcon.java
+++ b/jdk/src/share/classes/java/awt/TrayIcon.java
@@ -40,6 +40,8 @@ import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.HeadlessToolkit;
import java.util.EventObject;
+import java.security.AccessControlContext;
+import java.security.AccessController;
/**
* A TrayIcon object represents a tray icon that can be
@@ -90,6 +92,7 @@ import java.util.EventObject;
* @author Anton Tarasov
*/
public class TrayIcon {
+
private Image image;
private String tooltip;
private PopupMenu popup;
@@ -103,6 +106,24 @@ public class TrayIcon {
transient MouseMotionListener mouseMotionListener;
transient ActionListener actionListener;
+ /*
+ * The tray icon's AccessControlContext.
+ *
+ * Unlike the acc in Component, this field is made final
+ * because TrayIcon is not serializable.
+ */
+ private final AccessControlContext acc = AccessController.getContext();
+
+ /*
+ * Returns the acc this tray icon was constructed with.
+ */
+ final AccessControlContext getAccessControlContext() {
+ if (acc == null) {
+ throw new SecurityException("TrayIcon is missing AccessControlContext");
+ }
+ return acc;
+ }
+
static {
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
diff --git a/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-3.png b/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-3.png
new file mode 100644
index 00000000000..46484fdb766
Binary files /dev/null and b/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-3.png differ
diff --git a/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-4.png b/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-4.png
new file mode 100644
index 00000000000..6ab38c833ce
Binary files /dev/null and b/jdk/src/share/classes/java/awt/doc-files/RadialGradientPaint-4.png differ
diff --git a/jdk/src/share/classes/java/awt/image/PackedColorModel.java b/jdk/src/share/classes/java/awt/image/PackedColorModel.java
index 532f8d2678b..b2ab7ad9c91 100644
--- a/jdk/src/share/classes/java/awt/image/PackedColorModel.java
+++ b/jdk/src/share/classes/java/awt/image/PackedColorModel.java
@@ -343,8 +343,13 @@ public abstract class PackedColorModel extends ColorModel {
if (bitMasks.length != maskArray.length) {
return false;
}
+
+ /* compare 'effective' masks only, i.e. only part of the mask
+ * which fits the capacity of the transfer type.
+ */
+ int maxMask = (int)((1L << DataBuffer.getDataTypeSize(transferType)) - 1);
for (int i=0; i < bitMasks.length; i++) {
- if (bitMasks[i] != maskArray[i]) {
+ if ((maxMask & bitMasks[i]) != (maxMask & maskArray[i])) {
return false;
}
}
diff --git a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java
index d5c24edcb64..64570928afb 100644
--- a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java
+++ b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java
@@ -35,7 +35,7 @@ import sun.reflect.misc.*;
* is the delegate used by default for classes about
* which no information is available. The DefaultPersistenceDelegate
* provides, version resilient, public API-based persistence for
- * classes that follow the JavaBeans conventions without any class specific
+ * classes that follow the JavaBeans™ conventions without any class specific
* configuration.
*
* The key assumptions are that the class has a nullary constructor
diff --git a/jdk/src/share/classes/java/beans/DesignMode.java b/jdk/src/share/classes/java/beans/DesignMode.java
index 3080706c5a0..af86266dc3f 100644
--- a/jdk/src/share/classes/java/beans/DesignMode.java
+++ b/jdk/src/share/classes/java/beans/DesignMode.java
@@ -31,7 +31,7 @@ package java.beans;
* of java.beans.beancontext.BeanContext, in order to propagate to its nested hierarchy
* of java.beans.beancontext.BeanContextChild instances, the current "designTime" property.
*
- * The JavaBeans specification defines the notion of design time as is a
+ * The JavaBeans™ specification defines the notion of design time as is a
* mode in which JavaBeans instances should function during their composition
* and customization in a interactive design, composition or construction tool,
* as opposed to runtime when the JavaBean is part of an applet, application,
diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java b/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java
index a255ccabd8b..7ec03d8fb75 100644
--- a/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java
@@ -26,7 +26,7 @@ package java.beans;
/**
* An "IndexedPropertyChange" event gets delivered whenever a component that
- * conforms to the JavaBeans specification (a "bean") changes a bound
+ * conforms to the JavaBeans™ specification (a "bean") changes a bound
* indexed property. This class is an extension of PropertyChangeEvent
* but contains the index of the property that has changed.
*
diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java
index 9046da81719..5892df6cb29 100644
--- a/jdk/src/share/classes/java/beans/Introspector.java
+++ b/jdk/src/share/classes/java/beans/Introspector.java
@@ -87,7 +87,7 @@ import sun.reflect.misc.ReflectUtil;
*
* For more information about introspection and design patterns, please
* consult the
- * JavaBeans specification .
+ * JavaBeans™ specification .
*/
public class Introspector {
@@ -1245,7 +1245,7 @@ public class Introspector {
try {
type = ClassFinder.findClass(name, type.getClassLoader());
// Each customizer should inherit java.awt.Component and implement java.beans.Customizer
- // according to the section 9.3 of JavaBeans specification
+ // according to the section 9.3 of JavaBeans™ specification
if (Component.class.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) {
return type;
}
diff --git a/jdk/src/share/classes/java/beans/VetoableChangeSupport.java b/jdk/src/share/classes/java/beans/VetoableChangeSupport.java
index a8573da5fc9..d26f58a219d 100644
--- a/jdk/src/share/classes/java/beans/VetoableChangeSupport.java
+++ b/jdk/src/share/classes/java/beans/VetoableChangeSupport.java
@@ -474,7 +474,7 @@ public class VetoableChangeSupport implements Serializable {
/**
* @serialField children Hashtable
* @serialField source Object
- * @serialField propertyChangeSupportSerializedDataVersion int
+ * @serialField vetoableChangeSupportSerializedDataVersion int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("children", Hashtable.class),
diff --git a/jdk/src/share/classes/java/beans/package.html b/jdk/src/share/classes/java/beans/package.html
index 576e1f763dc..b1f0a8cf336 100644
--- a/jdk/src/share/classes/java/beans/package.html
+++ b/jdk/src/share/classes/java/beans/package.html
@@ -29,7 +29,7 @@
Contains classes related to developing
beans -- components
-based on the JavaBeansTM architecture.
+based on the JavaBeans™ architecture.
A few of the
classes are used by beans while they run in an application.
For example, the event classes are
diff --git a/jdk/src/share/classes/java/dyn/Linkage.java b/jdk/src/share/classes/java/dyn/Linkage.java
deleted file mode 100644
index 4ddda0a1990..00000000000
--- a/jdk/src/share/classes/java/dyn/Linkage.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, 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.dyn;
-
-import java.dyn.MethodHandles.Lookup;
-import java.util.WeakHashMap;
-import sun.dyn.Access;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.util.VerifyAccess;
-import sun.reflect.Reflection;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-
-/**
- * CLASS WILL BE REMOVED FOR PFD:
- * Static routines for controlling invokedynamic behavior.
- * Replaced by non-static APIs.
- * @author John Rose, JSR 292 EG
- * @deprecated This class will be removed in the Public Final Draft.
- */
-public class Linkage {
- private static final Access IMPL_TOKEN = Access.getToken();
-
- private Linkage() {} // do not instantiate
-
- /**
- * METHOD WILL BE REMOVED FOR PFD:
- * Register a bootstrap method to use when linking dynamic call sites within
- * a given caller class.
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
- Class callc = Reflection.getCallerClass(2);
- if (callc != null && !VerifyAccess.isSamePackage(callerClass, callc))
- throw new IllegalArgumentException("cannot set bootstrap method on "+callerClass);
- MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
- }
-
- /**
- * METHOD WILL BE REMOVED FOR PFD:
- * Simplified version of {@code registerBootstrapMethod} for self-registration,
- * to be called from a static initializer.
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(Class> runtime, String name) {
- Class callerClass = Reflection.getCallerClass(2);
- registerBootstrapMethodLookup(callerClass, runtime, name);
- }
-
- /**
- * METHOD WILL BE REMOVED FOR PFD:
- * Simplified version of {@code registerBootstrapMethod} for self-registration,
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(String name) {
- Class callerClass = Reflection.getCallerClass(2);
- registerBootstrapMethodLookup(callerClass, callerClass, name);
- }
-
- private static
- void registerBootstrapMethodLookup(Class> callerClass, Class> runtime, String name) {
- Lookup lookup = new Lookup(IMPL_TOKEN, callerClass);
- MethodHandle bootstrapMethod;
- try {
- bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
- } catch (ReflectiveOperationException ex) {
- throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
- }
- MethodHandleImpl.registerBootstrap(IMPL_TOKEN, callerClass, bootstrapMethod);
- }
-
- private static final MethodType BOOTSTRAP_METHOD_TYPE
- = MethodType.methodType(CallSite.class,
- Class.class, String.class, MethodType.class);
-
- /**
- * METHOD WILL BE REMOVED FOR PFD:
- * Invalidate all invokedynamic call sites everywhere.
- * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
- * {@link MutableCallSite#syncAll call site update pushing},
- * and {@link SwitchPoint#guardWithTest target switching} instead.
- */
- public static
- Object invalidateAll() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * METHOD WILL BE REMOVED FOR PFD:
- * Invalidate all {@code invokedynamic} call sites in the bytecodes
- * of any methods of the given class.
- * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
- * {@link MutableCallSite#syncAll call site update pushing},
- * and {@link SwitchPoint#guardWithTest target switching} instead.
- */
- public static
- Object invalidateCallerClass(Class> callerClass) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/jdk/src/share/classes/java/lang/AutoCloseable.java b/jdk/src/share/classes/java/lang/AutoCloseable.java
index f18de8cd5fb..54ecda38fed 100644
--- a/jdk/src/share/classes/java/lang/AutoCloseable.java
+++ b/jdk/src/share/classes/java/lang/AutoCloseable.java
@@ -34,12 +34,27 @@ package java.lang;
public interface AutoCloseable {
/**
* Closes this resource, relinquishing any underlying resources.
- * This method is invoked automatically by the {@code
- * try}-with-resources statement.
+ * This method is invoked automatically on objects managed by the
+ * {@code try}-with-resources statement.
*
- *
Classes implementing this method are strongly encouraged to
- * be declared to throw more specific exceptions (or no exception
- * at all, if the close cannot fail).
+ *
While this interface method is declared to throw {@code
+ * Exception}, implementers are strongly encouraged to
+ * declare concrete implementations of the {@code close} method to
+ * throw more specific exceptions, or to throw no exception at all
+ * if the close operation cannot fail.
+ *
+ *
Implementers of this interface are also strongly advised
+ * to not have the {@code close} method throw {@link
+ * InterruptedException}.
+ *
+ * This exception interacts with a thread's interrupted status,
+ * and runtime misbehavior is likely to occur if an {@code
+ * InterruptedException} is {@linkplain Throwable#addSuppressed
+ * suppressed}.
+ *
+ * More generally, if it would cause problems for an
+ * exception to be suppressed, the {@code AutoCloseable.close}
+ * method should not throw it.
*
*
Note that unlike the {@link java.io.Closeable#close close}
* method of {@link java.io.Closeable}, this {@code close} method
@@ -48,9 +63,8 @@ public interface AutoCloseable {
* visible side effect, unlike {@code Closeable.close} which is
* required to have no effect if called more than once.
*
- * However, while not required to be idempotent, implementers of
- * this interface are strongly encouraged to make their {@code
- * close} methods idempotent.
+ * However, implementers of this interface are strongly encouraged
+ * to make their {@code close} methods idempotent.
*
* @throws Exception if this resource cannot be closed
*/
diff --git a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java b/jdk/src/share/classes/java/lang/BootstrapMethodError.java
similarity index 66%
rename from jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
rename to jdk/src/share/classes/java/lang/BootstrapMethodError.java
index 76e795e2f0e..0fee75ad33d 100644
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java
+++ b/jdk/src/share/classes/java/lang/BootstrapMethodError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,58 +23,56 @@
* questions.
*/
-package java.dyn;
+package java.lang;
/**
* Thrown to indicate that an {@code invokedynamic} instruction has
- * failed to find its
- * {@linkplain BootstrapMethod bootstrap method},
- * or the bootstrap method has
- * failed to provide a
- * {@linkplain CallSite call site} with a {@linkplain CallSite#getTarget target}
- * of the correct {@linkplain MethodHandle#type method type}.
+ * failed to find its bootstrap method,
+ * or the bootstrap method has failed to provide a
+ * {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
+ * of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
*
* @author John Rose, JSR 292 EG
* @since 1.7
*/
-public class InvokeDynamicBootstrapError extends LinkageError {
+public class BootstrapMethodError extends LinkageError {
private static final long serialVersionUID = 292L;
/**
- * Constructs an {@code InvokeDynamicBootstrapError} with no detail message.
+ * Constructs an {@code BootstrapMethodError} with no detail message.
*/
- public InvokeDynamicBootstrapError() {
+ public BootstrapMethodError() {
super();
}
/**
- * Constructs an {@code InvokeDynamicBootstrapError} with the specified
+ * Constructs an {@code BootstrapMethodError} with the specified
* detail message.
*
* @param s the detail message.
*/
- public InvokeDynamicBootstrapError(String s) {
+ public BootstrapMethodError(String s) {
super(s);
}
/**
- * Constructs a {@code InvokeDynamicBootstrapError} with the specified
+ * Constructs a {@code BootstrapMethodError} with the specified
* detail message and cause.
*
* @param s the detail message.
* @param cause the cause, may be {@code null}.
*/
- public InvokeDynamicBootstrapError(String s, Throwable cause) {
+ public BootstrapMethodError(String s, Throwable cause) {
super(s, cause);
}
/**
- * Constructs a {@code InvokeDynamicBootstrapError} with the specified
+ * Constructs a {@code BootstrapMethodError} with the specified
* cause.
*
* @param cause the cause, may be {@code null}.
*/
- public InvokeDynamicBootstrapError(Throwable cause) {
+ public BootstrapMethodError(Throwable cause) {
// cf. Throwable(Throwable cause) constructor.
super(cause == null ? null : cause.toString());
initCause(cause);
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
index 37d7a30b583..2c0c7908566 100644
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2011, 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
@@ -1626,20 +1626,28 @@ public abstract class ClassLoader {
* @since 1.2
*/
protected Package getPackage(String name) {
+ Package pkg;
synchronized (packages) {
- Package pkg = packages.get(name);
- if (pkg == null) {
- if (parent != null) {
- pkg = parent.getPackage(name);
- } else {
- pkg = Package.getSystemPackage(name);
- }
- if (pkg != null) {
- packages.put(name, pkg);
+ pkg = packages.get(name);
+ }
+ if (pkg == null) {
+ if (parent != null) {
+ pkg = parent.getPackage(name);
+ } else {
+ pkg = Package.getSystemPackage(name);
+ }
+ if (pkg != null) {
+ synchronized (packages) {
+ Package pkg2 = packages.get(name);
+ if (pkg2 == null) {
+ packages.put(name, pkg);
+ } else {
+ pkg = pkg2;
+ }
}
}
- return pkg;
}
+ return pkg;
}
/**
diff --git a/jdk/src/share/classes/java/dyn/ClassValue.java b/jdk/src/share/classes/java/lang/ClassValue.java
similarity index 94%
rename from jdk/src/share/classes/java/dyn/ClassValue.java
rename to jdk/src/share/classes/java/lang/ClassValue.java
index 597dd951eb6..92c49a92ef2 100644
--- a/jdk/src/share/classes/java/dyn/ClassValue.java
+++ b/jdk/src/share/classes/java/lang/ClassValue.java
@@ -23,12 +23,10 @@
* questions.
*/
-package java.dyn;
+package java.lang;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.lang.reflect.UndeclaredThrowableException;
/**
* Lazily associate a computed value with (potentially) every type.
@@ -37,10 +35,11 @@ import java.lang.reflect.UndeclaredThrowableException;
* it can use a {@code ClassValue} to cache information needed to
* perform the message send quickly, for each class encountered.
* @author John Rose, JSR 292 EG
+ * @since 1.7
*/
public abstract class ClassValue {
/**
- * Compute the given class's derived value for this {@code ClassValue}.
+ * Computes the given class's derived value for this {@code ClassValue}.
*
* This method will be invoked within the first thread that accesses
* the value with the {@link #get get} method.
@@ -159,13 +158,7 @@ public abstract class ClassValue {
}
/// Implementation...
-
- // The hash code for this type is based on the identity of the object,
- // and is well-dispersed for power-of-two tables.
- /** @deprecated This override, which is implementation-specific, will be removed for PFD. */
- public final int hashCode() { return hashCode; }
- private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
- private static final AtomicInteger HASH_CODES = new AtomicInteger();
+ // FIXME: Use a data structure here similar that of ThreadLocal (7030453).
private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
diff --git a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java
similarity index 89%
rename from jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java
rename to jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java
index 676907c9185..a47b38f8bb3 100644
--- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java
@@ -23,20 +23,19 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import sun.dyn.util.VerifyType;
-import sun.dyn.util.Wrapper;
-import java.dyn.*;
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
import java.util.Arrays;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* This method handle performs simple conversion or checking of a single argument.
* @author jrose
*/
-public class AdapterMethodHandle extends BoundMethodHandle {
+class AdapterMethodHandle extends BoundMethodHandle {
//MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
//Object argument; // parameter to the conversion if needed
@@ -48,25 +47,21 @@ public class AdapterMethodHandle extends BoundMethodHandle {
long conv, Object convArg) {
super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
this.conversion = convCode(conv);
- if (MethodHandleNatives.JVM_SUPPORT) {
- // JVM might update VM-specific bits of conversion (ignore)
- MethodHandleNatives.init(this, target, convArgPos(conv));
- }
+ // JVM might update VM-specific bits of conversion (ignore)
+ MethodHandleNatives.init(this, target, convArgPos(conv));
}
private AdapterMethodHandle(MethodHandle target, MethodType newType,
long conv) {
this(target, newType, conv, null);
}
- private static final Access IMPL_TOKEN = Access.getToken();
-
// TO DO: When adapting another MH with a null conversion, clone
// the target and change its type, instead of adding another layer.
/** Can a JVM-level adapter directly implement the proposed
* argument conversions, as if by MethodHandles.convertArguments?
*/
- public static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
+ static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
// same number of args, of course
int len = newType.parameterCount();
if (len != oldType.parameterCount())
@@ -92,7 +87,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Can a JVM-level adapter directly implement the proposed
* argument conversion, as if by MethodHandles.convertArguments?
*/
- public static boolean canConvertArgument(Class> src, Class> dst) {
+ static boolean canConvertArgument(Class> src, Class> dst) {
// ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
// so we don't need to repeat so much decision making.
if (VerifyType.isNullConversion(src, dst)) {
@@ -118,16 +113,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* the JVM supports ricochet adapters).
* The argument conversions allowed are casting, unboxing,
* integral widening or narrowing, and floating point widening or narrowing.
- * @param token access check
* @param newType required call type
* @param target original method handle
* @return an adapter to the original handle with the desired new type,
* or the original target if the types are already identical
* or null if the adaptation cannot be made
*/
- public static MethodHandle makePairwiseConvert(Access token,
- MethodType newType, MethodHandle target) {
- Access.check(token);
+ static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target) {
MethodType oldType = target.type();
if (newType == oldType) return target;
@@ -170,9 +162,9 @@ public class AdapterMethodHandle extends BoundMethodHandle {
// It parallels canConvertArgument() above.
if (src.isPrimitive()) {
if (dst.isPrimitive()) {
- adapter = makePrimCast(token, midType, adapter, i, dst);
+ adapter = makePrimCast(midType, adapter, i, dst);
} else {
- adapter = makeBoxArgument(token, midType, adapter, i, dst);
+ adapter = makeBoxArgument(midType, adapter, i, dst);
}
} else {
if (dst.isPrimitive()) {
@@ -182,13 +174,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
// conversions supported by reflect.Method.invoke.
// Those conversions require a big nest of if/then/else logic,
// which we prefer to make a user responsibility.
- adapter = makeUnboxArgument(token, midType, adapter, i, dst);
+ adapter = makeUnboxArgument(midType, adapter, i, dst);
} else {
// Simple reference conversion.
// Note: Do not check for a class hierarchy relation
// between src and dst. In all cases a 'null' argument
// will pass the cast conversion.
- adapter = makeCheckCast(token, midType, adapter, i, dst);
+ adapter = makeCheckCast(midType, adapter, i, dst);
}
}
assert(adapter != null);
@@ -196,7 +188,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
if (adapter.type() != newType) {
// Only trivial conversions remain.
- adapter = makeRetypeOnly(IMPL_TOKEN, newType, adapter);
+ adapter = makeRetypeOnly(newType, adapter);
assert(adapter != null);
// Actually, that's because there were no non-trivial ones:
assert(lastConv == -1);
@@ -208,7 +200,6 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/**
* Create a JVM-level adapter method handle to permute the arguments
* of the given method.
- * @param token access check
* @param newType required call type
* @param target original method handle
* @param argumentMap for each target argument, position of its source in newType
@@ -218,8 +209,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* @throws IllegalArgumentException if the adaptation cannot be made
* directly by a JVM-level adapter, without help from Java code
*/
- public static MethodHandle makePermutation(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makePermutation(MethodType newType, MethodHandle target,
int[] argumentMap) {
MethodType oldType = target.type();
boolean nullPermutation = true;
@@ -234,7 +224,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
if (argumentMap.length != oldType.parameterCount())
throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
if (nullPermutation) {
- MethodHandle res = makePairwiseConvert(token, newType, target);
+ MethodHandle res = makePairwiseConvert(newType, target);
// well, that was easy
if (res == null)
throw newIllegalArgumentException("cannot convert pairwise: "+newType);
@@ -435,7 +425,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
/** Can a retyping adapter (alone) validly convert the target to newType? */
- public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
+ static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
return canRetype(newType, targetType, false);
}
/** Can a retyping adapter (alone) convert the target to newType?
@@ -444,7 +434,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* reference conversions on return. This last feature requires that the
* caller be trusted, and perform explicit cast conversions on return values.
*/
- public static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
+ static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
return canRetype(newType, targetType, true);
}
static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
@@ -459,17 +449,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* Allows unchecked argument conversions pairwise, if they are safe.
* Returns null if not possible.
*/
- public static MethodHandle makeRetypeOnly(Access token,
- MethodType newType, MethodHandle target) {
- return makeRetype(token, newType, target, false);
+ static MethodHandle makeRetypeOnly(MethodType newType, MethodHandle target) {
+ return makeRetype(newType, target, false);
}
- public static MethodHandle makeRetypeRaw(Access token,
- MethodType newType, MethodHandle target) {
- return makeRetype(token, newType, target, true);
+ static MethodHandle makeRetypeRaw(MethodType newType, MethodHandle target) {
+ return makeRetype(newType, target, true);
}
- static MethodHandle makeRetype(Access token,
- MethodType newType, MethodHandle target, boolean raw) {
- Access.check(token);
+ static MethodHandle makeRetype(MethodType newType, MethodHandle target, boolean raw) {
MethodType oldType = target.type();
if (oldType == newType) return target;
if (!canRetype(newType, oldType, raw))
@@ -478,9 +464,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
}
- static MethodHandle makeVarargsCollector(Access token,
- MethodHandle target, Class> arrayType) {
- Access.check(token);
+ static MethodHandle makeVarargsCollector(MethodHandle target, Class> arrayType) {
return new AsVarargsCollector(target, arrayType);
}
@@ -526,6 +510,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return collector.asType(newType);
}
+ @Override
public MethodHandle asVarargsCollector(Class> arrayType) {
MethodType type = this.type();
if (type.parameterType(type.parameterCount()-1) == arrayType)
@@ -537,7 +522,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Can a checkcast adapter validly convert the target to newType?
* The JVM supports all kind of reference casts, even silly ones.
*/
- public static boolean canCheckCast(MethodType newType, MethodType targetType,
+ static boolean canCheckCast(MethodType newType, MethodType targetType,
int arg, Class> castType) {
if (!convOpSupported(OP_CHECK_CAST)) return false;
Class> src = newType.parameterType(arg);
@@ -549,7 +534,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return (diff == arg+1); // arg is sole non-trivial diff
}
/** Can an primitive conversion adapter validly convert src to dst? */
- public static boolean canCheckCast(Class> src, Class> dst) {
+ static boolean canCheckCast(Class> src, Class> dst) {
return (!src.isPrimitive() && !dst.isPrimitive());
}
@@ -558,10 +543,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* with a null conversion to the corresponding target parameter.
* Return null if this cannot be done.
*/
- public static MethodHandle makeCheckCast(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeCheckCast(MethodType newType, MethodHandle target,
int arg, Class> castType) {
- Access.check(token);
if (!canCheckCast(newType, target.type(), arg, castType))
return null;
long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
@@ -572,7 +555,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* The JVM currently supports all conversions except those between
* floating and integral types.
*/
- public static boolean canPrimCast(MethodType newType, MethodType targetType,
+ static boolean canPrimCast(MethodType newType, MethodType targetType,
int arg, Class> convType) {
if (!convOpSupported(OP_PRIM_TO_PRIM)) return false;
Class> src = newType.parameterType(arg);
@@ -584,7 +567,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return (diff == arg+1); // arg is sole non-trivial diff
}
/** Can an primitive conversion adapter validly convert src to dst? */
- public static boolean canPrimCast(Class> src, Class> dst) {
+ static boolean canPrimCast(Class> src, Class> dst) {
if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
return false;
} else if (Wrapper.forPrimitiveType(dst).isFloating()) {
@@ -604,10 +587,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* with a null conversion to the corresponding target parameter.
* Return null if this cannot be done.
*/
- public static MethodHandle makePrimCast(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makePrimCast(MethodType newType, MethodHandle target,
int arg, Class> convType) {
- Access.check(token);
MethodType oldType = target.type();
if (!canPrimCast(newType, oldType, arg, convType))
return null;
@@ -620,7 +601,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* The JVM currently supports all kinds of casting and unboxing.
* The convType is the unboxed type; it can be either a primitive or wrapper.
*/
- public static boolean canUnboxArgument(MethodType newType, MethodType targetType,
+ static boolean canUnboxArgument(MethodType newType, MethodType targetType,
int arg, Class> convType) {
if (!convOpSupported(OP_REF_TO_PRIM)) return false;
Class> src = newType.parameterType(arg);
@@ -635,15 +616,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return (diff == arg+1); // arg is sole non-trivial diff
}
/** Can an primitive unboxing adapter validly convert src to dst? */
- public static boolean canUnboxArgument(Class> src, Class> dst) {
+ static boolean canUnboxArgument(Class> src, Class> dst) {
return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
}
/** Factory method: Unbox the given argument.
* Return null if this cannot be done.
*/
- public static MethodHandle makeUnboxArgument(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeUnboxArgument(MethodType newType, MethodHandle target,
int arg, Class> convType) {
MethodType oldType = target.type();
Class> src = newType.parameterType(arg);
@@ -659,11 +639,11 @@ public class AdapterMethodHandle extends BoundMethodHandle {
MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
if (castDone == newType)
return adapter;
- return makeCheckCast(token, newType, adapter, arg, boxType);
+ return makeCheckCast(newType, adapter, arg, boxType);
}
/** Can an primitive boxing adapter validly convert src to dst? */
- public static boolean canBoxArgument(Class> src, Class> dst) {
+ static boolean canBoxArgument(Class> src, Class> dst) {
if (!convOpSupported(OP_PRIM_TO_REF)) return false;
throw new UnsupportedOperationException("NYI");
}
@@ -671,15 +651,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Unbox the given argument.
* Return null if this cannot be done.
*/
- public static MethodHandle makeBoxArgument(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeBoxArgument(MethodType newType, MethodHandle target,
int arg, Class> convType) {
// this is difficult to do in the JVM because it must GC
return null;
}
/** Can an adapter simply drop arguments to convert the target to newType? */
- public static boolean canDropArguments(MethodType newType, MethodType targetType,
+ static boolean canDropArguments(MethodType newType, MethodType targetType,
int dropArgPos, int dropArgCount) {
if (dropArgCount == 0)
return canRetypeOnly(newType, targetType);
@@ -706,12 +685,10 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* Allow unchecked retyping of remaining arguments, pairwise.
* Return null if this is not possible.
*/
- public static MethodHandle makeDropArguments(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeDropArguments(MethodType newType, MethodHandle target,
int dropArgPos, int dropArgCount) {
- Access.check(token);
if (dropArgCount == 0)
- return makeRetypeOnly(IMPL_TOKEN, newType, target);
+ return makeRetypeOnly(newType, target);
if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount))
return null;
// in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
@@ -727,7 +704,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
/** Can an adapter duplicate an argument to convert the target to newType? */
- public static boolean canDupArguments(MethodType newType, MethodType targetType,
+ static boolean canDupArguments(MethodType newType, MethodType targetType,
int dupArgPos, int dupArgCount) {
if (!convOpSupported(OP_DUP_ARGS)) return false;
if (diffReturnTypes(newType, targetType, false) != 0)
@@ -749,10 +726,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Duplicate the selected argument.
* Return null if this is not possible.
*/
- public static MethodHandle makeDupArguments(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeDupArguments(MethodType newType, MethodHandle target,
int dupArgPos, int dupArgCount) {
- Access.check(token);
if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
return null;
if (dupArgCount == 0)
@@ -769,7 +744,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
/** Can an adapter swap two arguments to convert the target to newType? */
- public static boolean canSwapArguments(MethodType newType, MethodType targetType,
+ static boolean canSwapArguments(MethodType newType, MethodType targetType,
int swapArg1, int swapArg2) {
if (!convOpSupported(OP_SWAP_ARGS)) return false;
if (diffReturnTypes(newType, targetType, false) != 0)
@@ -796,10 +771,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Swap the selected arguments.
* Return null if this is not possible.
*/
- public static MethodHandle makeSwapArguments(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeSwapArguments(MethodType newType, MethodHandle target,
int swapArg1, int swapArg2) {
- Access.check(token);
if (swapArg1 == swapArg2)
return target;
if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
@@ -829,7 +802,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
final static int MAX_ARG_ROTATION = 1;
/** Can an adapter rotate arguments to convert the target to newType? */
- public static boolean canRotateArguments(MethodType newType, MethodType targetType,
+ static boolean canRotateArguments(MethodType newType, MethodType targetType,
int firstArg, int argCount, int rotateBy) {
if (!convOpSupported(OP_ROT_ARGS)) return false;
if (argCount <= 2) return false; // must be a swap, not a rotate
@@ -861,10 +834,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Rotate the selected argument range.
* Return null if this is not possible.
*/
- public static MethodHandle makeRotateArguments(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeRotateArguments(MethodType newType, MethodHandle target,
int firstArg, int argCount, int rotateBy) {
- Access.check(token);
rotateBy = positiveRotation(argCount, rotateBy);
if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy))
return null;
@@ -904,7 +875,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
/** Can an adapter spread an argument to convert the target to newType? */
- public static boolean canSpreadArguments(MethodType newType, MethodType targetType,
+ static boolean canSpreadArguments(MethodType newType, MethodType targetType,
Class> spreadArgType, int spreadArgPos, int spreadArgCount) {
if (!convOpSupported(OP_SPREAD_ARGS)) return false;
if (diffReturnTypes(newType, targetType, false) != 0)
@@ -937,10 +908,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Spread selected argument. */
- public static MethodHandle makeSpreadArguments(Access token,
- MethodType newType, MethodHandle target,
+ static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
Class> spreadArgType, int spreadArgPos, int spreadArgCount) {
- Access.check(token);
MethodType targetType = target.type();
if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
return null;
@@ -962,7 +931,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
@Override
public String toString() {
- return MethodHandleImpl.getNameString(IMPL_TOKEN, nonAdapter((MethodHandle)vmtarget), this);
+ return getNameString(nonAdapter((MethodHandle)vmtarget), this);
}
private static MethodHandle nonAdapter(MethodHandle mh) {
diff --git a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
similarity index 80%
rename from jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
rename to jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
index 0fab63f7c77..d0d78895e77 100644
--- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,15 +23,11 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import sun.dyn.util.VerifyType;
-import sun.dyn.util.Wrapper;
-import java.dyn.*;
-import java.util.List;
-import sun.dyn.MethodHandleNatives.Constants;
-import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* The flavor of method handle which emulates an invoke instruction
@@ -39,37 +35,29 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* when the handle is created, not when it is invoked.
* @author jrose
*/
-public class BoundMethodHandle extends MethodHandle {
+class BoundMethodHandle extends MethodHandle {
//MethodHandle vmtarget; // next BMH or final DMH or methodOop
private final Object argument; // argument to insert
private final int vmargslot; // position at which it is inserted
- private static final Access IMPL_TOKEN = Access.getToken();
- private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
-
// Constructors in this class *must* be package scoped or private.
/** Bind a direct MH to its receiver (or first ref. argument).
* The JVM will pre-dispatch the MH if it is not already static.
*/
- BoundMethodHandle(DirectMethodHandle mh, Object argument) {
- super(Access.TOKEN, mh.type().dropParameterTypes(0, 1));
+ /*non-public*/ BoundMethodHandle(DirectMethodHandle mh, Object argument) {
+ super(mh.type().dropParameterTypes(0, 1));
// check the type now, once for all:
this.argument = checkReferenceArgument(argument, mh, 0);
this.vmargslot = this.type().parameterSlotCount();
- if (MethodHandleNatives.JVM_SUPPORT) {
- this.vmtarget = null; // maybe updated by JVM
- MethodHandleNatives.init(this, mh, 0);
- } else {
- this.vmtarget = mh;
- }
+ initTarget(mh, 0);
}
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
* The argument type must be a reference.
*/
- BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
+ /*non-public*/ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
this(mh.type().dropParameterTypes(argnum, argnum+1),
mh, argument, argnum);
}
@@ -77,8 +65,8 @@ public class BoundMethodHandle extends MethodHandle {
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
*/
- BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
- super(Access.TOKEN, type);
+ /*non-public*/ BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
+ super(type);
if (mh.type().parameterType(argnum).isPrimitive())
this.argument = bindPrimitiveArgument(argument, mh, argnum);
else {
@@ -89,18 +77,14 @@ public class BoundMethodHandle extends MethodHandle {
}
private void initTarget(MethodHandle mh, int argnum) {
- if (MethodHandleNatives.JVM_SUPPORT) {
- this.vmtarget = null; // maybe updated by JVM
- MethodHandleNatives.init(this, mh, argnum);
- } else {
- this.vmtarget = mh;
- }
+ //this.vmtarget = mh; // maybe updated by JVM
+ MethodHandleNatives.init(this, mh, argnum);
}
/** For the AdapterMethodHandle subclass.
*/
- BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
- super(Access.TOKEN, type);
+ /*non-public*/ BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
+ super(type);
this.argument = argument;
this.vmargslot = vmargslot;
assert(this instanceof AdapterMethodHandle);
@@ -112,8 +96,8 @@ public class BoundMethodHandle extends MethodHandle {
* same as {@code entryPoint}, except that the first argument
* type will be dropped.
*/
- protected BoundMethodHandle(Access token, MethodHandle entryPoint) {
- super(token, entryPoint.type().dropParameterTypes(0, 1));
+ /*non-public*/ BoundMethodHandle(MethodHandle entryPoint) {
+ super(entryPoint.type().dropParameterTypes(0, 1));
this.argument = this; // kludge; get rid of
this.vmargslot = this.type().parameterSlotDepth(0);
initTarget(entryPoint, 0);
@@ -172,7 +156,7 @@ public class BoundMethodHandle extends MethodHandle {
@Override
public String toString() {
- return MethodHandleImpl.addTypeString(baseName(), this);
+ return addTypeString(baseName(), this);
}
/** Component of toString() before the type string. */
diff --git a/jdk/src/share/classes/java/dyn/CallSite.java b/jdk/src/share/classes/java/lang/invoke/CallSite.java
similarity index 75%
rename from jdk/src/share/classes/java/dyn/CallSite.java
rename to jdk/src/share/classes/java/lang/invoke/CallSite.java
index 42af08a729b..b2da146d261 100644
--- a/jdk/src/share/classes/java/dyn/CallSite.java
+++ b/jdk/src/share/classes/java/lang/invoke/CallSite.java
@@ -23,12 +23,12 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
-import sun.dyn.*;
-import sun.dyn.empty.Empty;
+import sun.invoke.empty.Empty;
import sun.misc.Unsafe;
-import java.util.Collection;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
@@ -85,7 +85,6 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam
*/
abstract
public class CallSite {
- private static final Access IMPL_TOKEN = Access.getToken();
static { MethodHandleImpl.initStatics(); }
// Fields used only by the JVM. Do not use or change.
@@ -96,9 +95,6 @@ public class CallSite {
/*package-private*/
MethodHandle target;
- // Remove this field for PFD and delete deprecated methods:
- private MemberName calleeNameRemoveForPFD;
-
/**
* Make a blank call site object with the given method type.
* An initial target method is supplied which will throw
@@ -111,7 +107,7 @@ public class CallSite {
*/
/*package-private*/
CallSite(MethodType type) {
- target = MethodHandles.invokers(type).uninitializedCallSite();
+ target = type.invokers().uninitializedCallSite();
}
/**
@@ -145,7 +141,7 @@ public class CallSite {
int callerBCI) {
if (this.vmmethod != null) {
// FIXME
- throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction");
+ throw new BootstrapMethodError("call site has already been linked to an invokedynamic instruction");
}
if (!this.type().equals(type)) {
throw wrongTargetType(target, type);
@@ -202,7 +198,7 @@ public class CallSite {
}
/**
- * Produce a method handle equivalent to an invokedynamic instruction
+ * Produces a method handle equivalent to an invokedynamic instruction
* which has been linked to this call site.
*
* This method is equivalent to the following code:
@@ -218,7 +214,7 @@ public class CallSite {
public abstract MethodHandle dynamicInvoker();
/*non-public*/ MethodHandle makeDynamicInvoker() {
- MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, GET_TARGET, this);
+ MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget);
}
@@ -226,7 +222,7 @@ public class CallSite {
private static final MethodHandle GET_TARGET;
static {
try {
- GET_TARGET = MethodHandles.Lookup.IMPL_LOOKUP.
+ GET_TARGET = IMPL_LOOKUP.
findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
} catch (ReflectiveOperationException ignore) {
throw new InternalError();
@@ -252,7 +248,6 @@ public class CallSite {
/*package-private*/
void setTargetNormal(MethodHandle newTarget) {
target = newTarget;
- //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
}
/*package-private*/
MethodHandle getTargetVolatile() {
@@ -261,6 +256,68 @@ public class CallSite {
/*package-private*/
void setTargetVolatile(MethodHandle newTarget) {
unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
- //CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
+ }
+
+ // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
+ static CallSite makeSite(MethodHandle bootstrapMethod,
+ // Callee information:
+ String name, MethodType type,
+ // Extra arguments for BSM, if any:
+ Object info,
+ // Caller information:
+ MemberName callerMethod, int callerBCI) {
+ Class> callerClass = callerMethod.getDeclaringClass();
+ Object caller = IMPL_LOOKUP.in(callerClass);
+ CallSite site;
+ try {
+ Object binding;
+ info = maybeReBox(info);
+ if (info == null) {
+ binding = bootstrapMethod.invokeGeneric(caller, name, type);
+ } else if (!info.getClass().isArray()) {
+ binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
+ } else {
+ Object[] argv = (Object[]) info;
+ maybeReBoxElements(argv);
+ if (3 + argv.length > 255)
+ throw new BootstrapMethodError("too many bootstrap method arguments");
+ MethodType bsmType = bootstrapMethod.type();
+ if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
+ binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
+ else
+ binding = MethodHandles.spreadInvoker(bsmType, 3)
+ .invokeGeneric(bootstrapMethod, caller, name, type, argv);
+ }
+ //System.out.println("BSM for "+name+type+" => "+binding);
+ if (binding instanceof CallSite) {
+ site = (CallSite) binding;
+ } else {
+ throw new ClassCastException("bootstrap method failed to produce a CallSite");
+ }
+ assert(site.getTarget() != null);
+ assert(site.getTarget().type().equals(type));
+ } catch (Throwable ex) {
+ BootstrapMethodError bex;
+ if (ex instanceof BootstrapMethodError)
+ bex = (BootstrapMethodError) ex;
+ else
+ bex = new BootstrapMethodError("call site initialization exception", ex);
+ throw bex;
+ }
+ return site;
+ }
+
+ private static Object maybeReBox(Object x) {
+ if (x instanceof Integer) {
+ int xi = (int) x;
+ if (xi == (byte) xi)
+ x = xi; // must rebox; see JLS 5.1.7
+ }
+ return x;
+ }
+ private static void maybeReBoxElements(Object[] xa) {
+ for (int i = 0; i < xa.length; i++) {
+ xa[i] = maybeReBox(xa[i]);
+ }
}
}
diff --git a/jdk/src/share/classes/java/dyn/ConstantCallSite.java b/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java
similarity index 99%
rename from jdk/src/share/classes/java/dyn/ConstantCallSite.java
rename to jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java
index 50240a0f50f..e182c54aaa9 100644
--- a/jdk/src/share/classes/java/dyn/ConstantCallSite.java
+++ b/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java
@@ -23,7 +23,7 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
/**
* A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
diff --git a/jdk/src/share/classes/sun/dyn/DirectMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java
similarity index 91%
rename from jdk/src/share/classes/sun/dyn/DirectMethodHandle.java
rename to jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java
index b43f353bbd6..13bedb17859 100644
--- a/jdk/src/share/classes/sun/dyn/DirectMethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,10 +23,9 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import static sun.dyn.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
/**
* The flavor of method handle which emulates invokespecial or invokestatic.
@@ -39,7 +38,7 @@ class DirectMethodHandle extends MethodHandle {
// Constructors in this class *must* be package scoped or private.
DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class> lookupClass) {
- super(Access.TOKEN, mtype);
+ super(mtype);
assert(m.isMethod() || !doDispatch && m.isConstructor());
if (!m.isResolved())
diff --git a/jdk/src/share/classes/sun/dyn/FilterGeneric.java b/jdk/src/share/classes/java/lang/invoke/FilterGeneric.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/FilterGeneric.java
rename to jdk/src/share/classes/java/lang/invoke/FilterGeneric.java
index e77d742a11e..6c3395002f5 100644
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java
+++ b/jdk/src/share/classes/java/lang/invoke/FilterGeneric.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,11 +23,11 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
import java.lang.reflect.*;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* These adapters apply arbitrary conversions to arguments
@@ -123,7 +123,7 @@ class FilterGeneric {
MethodType entryType = entryType(kind, pos, filterType, targetType);
if (entryType.generic() != entryType)
throw newIllegalArgumentException("must be generic: "+entryType);
- MethodTypeImpl form = MethodTypeImpl.of(entryType);
+ MethodTypeForm form = entryType.form();
FilterGeneric filterGen = form.filterGeneric;
if (filterGen == null)
form.filterGeneric = filterGen = new FilterGeneric(entryType);
@@ -186,7 +186,7 @@ class FilterGeneric {
// see if it has the required invoke method
MethodHandle entryPoint = null;
try {
- entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
} catch (ReflectiveOperationException ex) {
}
if (entryPoint == null) continue;
@@ -231,7 +231,7 @@ class FilterGeneric {
@Override
public String toString() {
- return MethodHandleImpl.addTypeString(target, this);
+ return addTypeString(target, this);
}
protected boolean isPrototype() { return target == null; }
@@ -246,7 +246,7 @@ class FilterGeneric {
protected Adapter(MethodHandle entryPoint,
MethodHandle filter, MethodHandle target) {
- super(Access.TOKEN, entryPoint);
+ super(entryPoint);
this.filter = filter;
this.target = target;
}
@@ -256,7 +256,7 @@ class FilterGeneric {
MethodHandle filter, MethodHandle target);
// { return new ThisType(entryPoint, filter, target); }
- static private final String CLASS_PREFIX; // "sun.dyn.FilterGeneric$"
+ static private final String CLASS_PREFIX; // "java.lang.invoke.FilterGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
diff --git a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java b/jdk/src/share/classes/java/lang/invoke/FilterOneArgument.java
similarity index 86%
rename from jdk/src/share/classes/sun/dyn/FilterOneArgument.java
rename to jdk/src/share/classes/java/lang/invoke/FilterOneArgument.java
index 86c722f3c0a..64a9f072797 100644
--- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java
+++ b/jdk/src/share/classes/java/lang/invoke/FilterOneArgument.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,10 +23,10 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import static sun.dyn.MemberName.uncaughtException;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* Unary function composition, useful for many small plumbing jobs.
@@ -36,7 +36,7 @@ import static sun.dyn.MemberName.uncaughtException;
* final method type is the responsibility of a JVM-level adapter.
* @author jrose
*/
-public class FilterOneArgument extends BoundMethodHandle {
+class FilterOneArgument extends BoundMethodHandle {
protected final MethodHandle filter; // Object -> Object
protected final MethodHandle target; // Object -> Object
@@ -54,15 +54,15 @@ public class FilterOneArgument extends BoundMethodHandle {
static {
try {
INVOKE =
- MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
- MethodType.genericMethodType(1));
+ IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
+ MethodType.genericMethodType(1));
} catch (ReflectiveOperationException ex) {
throw uncaughtException(ex);
}
}
protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
- super(Access.TOKEN, INVOKE);
+ super(INVOKE);
this.filter = filter;
this.target = target;
}
diff --git a/jdk/src/share/classes/sun/dyn/FromGeneric.java b/jdk/src/share/classes/java/lang/invoke/FromGeneric.java
similarity index 97%
rename from jdk/src/share/classes/sun/dyn/FromGeneric.java
rename to jdk/src/share/classes/java/lang/invoke/FromGeneric.java
index b996a6b3ead..1c0523a4a36 100644
--- a/jdk/src/share/classes/sun/dyn/FromGeneric.java
+++ b/jdk/src/share/classes/java/lang/invoke/FromGeneric.java
@@ -23,12 +23,13 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
import java.lang.reflect.*;
-import sun.dyn.util.*;
-import static sun.dyn.MethodTypeImpl.invokers;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* Adapters which mediate between incoming calls which are generic
@@ -82,8 +83,8 @@ class FromGeneric {
}
// outgoing primitive arguments will be wrapped; unwrap them
- MethodType primsAsObj = MethodTypeImpl.of(targetType).primArgsAsBoxes();
- MethodType objArgsRawRet = MethodTypeImpl.of(primsAsObj).primsAsInts();
+ MethodType primsAsObj = targetType.form().primArgsAsBoxes();
+ MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
if (objArgsRawRet != targetType)
ad = findAdapter(internalType0 = objArgsRawRet);
if (ad == null) {
@@ -129,16 +130,16 @@ class FromGeneric {
MethodType targetType, MethodType internalType) {
// All the adapters we have here have reference-untyped internal calls.
assert(internalType == internalType.erase());
- MethodHandle invoker = invokers(targetType).exactInvoker();
+ MethodHandle invoker = targetType.invokers().exactInvoker();
// cast all narrow reference types, unbox all primitive arguments:
MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
- MethodHandle fixArgs = AdapterMethodHandle.convertArguments(Access.TOKEN,
+ MethodHandle fixArgs = MethodHandleImpl.convertArguments(
invoker, Invokers.invokerType(fixArgsType),
invoker.type(), null);
if (fixArgs == null)
throw new InternalError("bad fixArgs");
// reinterpret the calling sequence as raw:
- MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN,
+ MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
Invokers.invokerType(internalType), fixArgs);
if (retyper == null)
throw new InternalError("bad retyper");
@@ -171,7 +172,7 @@ class FromGeneric {
/** Return the adapter information for this type's erasure. */
static FromGeneric of(MethodType type) {
- MethodTypeImpl form = MethodTypeImpl.of(type);
+ MethodTypeForm form = type.form();
FromGeneric fromGen = form.fromGeneric;
if (fromGen == null)
form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
@@ -185,7 +186,7 @@ class FromGeneric {
/* Create an adapter that handles spreading calls for the given type. */
static Adapter findAdapter(MethodType internalType) {
MethodType entryType = internalType.generic();
- MethodTypeImpl form = MethodTypeImpl.of(internalType);
+ MethodTypeForm form = internalType.form();
Class> rtype = internalType.returnType();
int argc = form.parameterCount();
int lac = form.longPrimitiveParameterCount();
@@ -203,7 +204,7 @@ class FromGeneric {
// see if it has the required invoke method
MethodHandle entryPoint = null;
try {
- entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
} catch (ReflectiveOperationException ex) {
}
if (entryPoint == null) continue;
@@ -257,7 +258,7 @@ class FromGeneric {
@Override
public String toString() {
- return MethodHandleImpl.addTypeString(target, this);
+ return addTypeString(target, this);
}
protected boolean isPrototype() { return target == null; }
@@ -272,7 +273,7 @@ class FromGeneric {
protected Adapter(MethodHandle entryPoint,
MethodHandle invoker, MethodHandle convert, MethodHandle target) {
- super(Access.TOKEN, entryPoint);
+ super(entryPoint);
this.invoker = invoker;
this.convert = convert;
this.target = target;
@@ -290,7 +291,7 @@ class FromGeneric {
protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); }
protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
- static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
+ static private final String CLASS_PREFIX; // "java.lang.invoke.FromGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
diff --git a/jdk/src/share/classes/java/dyn/InvokeDynamic.java b/jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java
similarity index 93%
rename from jdk/src/share/classes/java/dyn/InvokeDynamic.java
rename to jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java
index 9c3ede1ee36..4668d741bbb 100644
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
/**
* This is a place-holder class. Some HotSpot implementations need to see it.
diff --git a/jdk/src/share/classes/sun/dyn/InvokeGeneric.java b/jdk/src/share/classes/java/lang/invoke/InvokeGeneric.java
similarity index 86%
rename from jdk/src/share/classes/sun/dyn/InvokeGeneric.java
rename to jdk/src/share/classes/java/lang/invoke/InvokeGeneric.java
index 0d1a5defce3..a235e7318da 100644
--- a/jdk/src/share/classes/sun/dyn/InvokeGeneric.java
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeGeneric.java
@@ -23,15 +23,13 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import java.lang.reflect.*;
-import sun.dyn.util.*;
-import static sun.dyn.MethodTypeImpl.invokers;
+import sun.invoke.util.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
- * Adapters which manage MethodHanndle.invokeGeneric calls.
+ * Adapters which manage MethodHandle.invokeGeneric calls.
* The JVM calls one of these when the exact type match fails.
* @author jrose
*/
@@ -44,7 +42,8 @@ class InvokeGeneric {
/** Compute and cache information for this adapter, so that it can
* call out to targets of the erasure-family of the given erased type.
*/
- private InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
+ /*non-public*/ InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
+ assert(erasedCallerType.equals(erasedCallerType.erase()));
this.erasedCallerType = erasedCallerType;
this.initialInvoker = makeInitialInvoker();
assert initialInvoker.type().equals(erasedCallerType
@@ -53,22 +52,13 @@ class InvokeGeneric {
}
private static MethodHandles.Lookup lookup() {
- return MethodHandleImpl.IMPL_LOOKUP;
+ return IMPL_LOOKUP;
}
/** Return the adapter information for this type's erasure. */
- static MethodHandle genericInvokerOf(MethodType type) {
- MethodTypeImpl form = MethodTypeImpl.of(type);
- MethodHandle genericInvoker = form.genericInvoker;
- if (genericInvoker == null) {
- try {
- InvokeGeneric gen = new InvokeGeneric(form.erasedType());
- form.genericInvoker = genericInvoker = gen.initialInvoker;
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- }
- return genericInvoker;
+ /*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
+ InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
+ return gen.initialInvoker;
}
private MethodHandle makeInitialInvoker() throws ReflectiveOperationException {
@@ -88,7 +78,7 @@ class InvokeGeneric {
private MethodHandle makePostDispatchInvoker() {
// Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
- return invokers(invokerType).exactInvoker();
+ return invokerType.invokers().exactInvoker();
}
private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
@@ -112,7 +102,7 @@ class InvokeGeneric {
if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
MethodHandle newTarget = target.asType(callerType);
targetType = callerType;
- Invokers invokers = MethodTypeImpl.invokers(Access.TOKEN, targetType);
+ Invokers invokers = targetType.invokers();
MethodHandle invoker = invokers.erasedInvokerWithDrops;
if (invoker == null) {
invokers.erasedInvokerWithDrops = invoker =
diff --git a/jdk/src/share/classes/sun/dyn/Invokers.java b/jdk/src/share/classes/java/lang/invoke/Invokers.java
similarity index 87%
rename from jdk/src/share/classes/sun/dyn/Invokers.java
rename to jdk/src/share/classes/java/lang/invoke/Invokers.java
index 55eef1911ba..4eeb36f76b7 100644
--- a/jdk/src/share/classes/sun/dyn/Invokers.java
+++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java
@@ -23,16 +23,16 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import sun.dyn.empty.Empty;
+import sun.invoke.empty.Empty;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* Construction and caching of often-used invokers.
* @author jrose
*/
-public class Invokers {
+class Invokers {
// exact type (sans leading taget MH) for the outgoing call
private final MethodType targetType;
@@ -60,15 +60,15 @@ public class Invokers {
this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
}
- public static MethodType invokerType(MethodType targetType) {
+ /*non-public*/ static MethodType invokerType(MethodType targetType) {
return targetType.insertParameterTypes(0, MethodHandle.class);
}
- public MethodHandle exactInvoker() {
+ /*non-public*/ MethodHandle exactInvoker() {
MethodHandle invoker = exactInvoker;
if (invoker != null) return invoker;
try {
- invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
+ invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
} catch (ReflectiveOperationException ex) {
throw new InternalError("JVM cannot find invoker for "+targetType);
}
@@ -77,7 +77,7 @@ public class Invokers {
return invoker;
}
- public MethodHandle genericInvoker() {
+ /*non-public*/ MethodHandle genericInvoker() {
MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = genericInvoker;
if (invoker != null) return invoker;
@@ -87,7 +87,7 @@ public class Invokers {
return invoker;
}
- public MethodHandle erasedInvoker() {
+ /*non-public*/ MethodHandle erasedInvoker() {
MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = erasedInvoker;
if (invoker != null) return invoker;
@@ -100,7 +100,7 @@ public class Invokers {
return invoker;
}
- public MethodHandle spreadInvoker(int objectArgCount) {
+ /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
MethodHandle vaInvoker = spreadInvokers[objectArgCount];
if (vaInvoker != null) return vaInvoker;
MethodHandle gInvoker = genericInvoker();
@@ -111,12 +111,12 @@ public class Invokers {
private static MethodHandle THROW_UCS = null;
- public MethodHandle uninitializedCallSite() {
+ /*non-public*/ MethodHandle uninitializedCallSite() {
MethodHandle invoker = uninitializedCallSite;
if (invoker != null) return invoker;
if (targetType.parameterCount() > 0) {
MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
- Invokers invokers0 = MethodTypeImpl.invokers(type0);
+ Invokers invokers0 = type0.invokers();
invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
0, targetType.parameterList());
assert(invoker.type().equals(targetType));
@@ -125,14 +125,14 @@ public class Invokers {
}
if (THROW_UCS == null) {
try {
- THROW_UCS = MethodHandleImpl.IMPL_LOOKUP
+ THROW_UCS = IMPL_LOOKUP
.findStatic(CallSite.class, "uninitializedCallSite",
MethodType.methodType(Empty.class));
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
}
- invoker = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, targetType, THROW_UCS);
+ invoker = AdapterMethodHandle.makeRetypeRaw(targetType, THROW_UCS);
assert(invoker.type().equals(targetType));
uninitializedCallSite = invoker;
return invoker;
diff --git a/jdk/src/share/classes/sun/dyn/MemberName.java b/jdk/src/share/classes/java/lang/invoke/MemberName.java
similarity index 93%
rename from jdk/src/share/classes/sun/dyn/MemberName.java
rename to jdk/src/share/classes/java/lang/invoke/MemberName.java
index 5e98b85ca60..0300fe758cc 100644
--- a/jdk/src/share/classes/sun/dyn/MemberName.java
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java
@@ -23,10 +23,9 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import sun.dyn.util.BytecodeDescriptor;
-import java.dyn.*;
+import sun.invoke.util.BytecodeDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -37,7 +36,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import static sun.dyn.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* A {@code MemberName} is a compact symbolic datum which fully characterizes
@@ -66,7 +66,7 @@ import static sun.dyn.MethodHandleNatives.Constants.*;
* and those seven fields omit much of the information in Method.
* @author jrose
*/
-public final class MemberName implements Member, Cloneable {
+/*non-public*/ final class MemberName implements Member, Cloneable {
private Class> clazz; // class in which the method is defined
private String name; // may be null if not yet materialized
private Object type; // may be null if not yet materialized
@@ -435,7 +435,7 @@ public final class MemberName implements Member, Cloneable {
/** Query whether this member name is resolved to a non-static, non-final method.
*/
public boolean hasReceiverTypeDispatch() {
- return (isMethod() && getVMIndex(Access.TOKEN) >= 0);
+ return (isMethod() && getVMIndex() >= 0);
}
/** Produce a string form of this member name.
@@ -490,59 +490,38 @@ public final class MemberName implements Member, Cloneable {
// Queries to the JVM:
/** Document? */
- public int getVMIndex(Access token) {
- Access.check(token);
+ /*non-public*/ int getVMIndex() {
if (!isResolved())
- throw newIllegalStateException("not resolved");
+ throw newIllegalStateException("not resolved", this);
return vmindex;
}
-// public Object getVMTarget(Access token) {
-// Access.check(token);
+// /*non-public*/ Object getVMTarget() {
// if (!isResolved())
-// throw newIllegalStateException("not resolved");
+// throw newIllegalStateException("not resolved", this);
// return vmtarget;
// }
- private RuntimeException newIllegalStateException(String message) {
- return new IllegalStateException(message+": "+this);
- }
- // handy shared exception makers (they simplify the common case code)
- public static RuntimeException newIllegalArgumentException(String message) {
- return new IllegalArgumentException(message);
- }
- public static IllegalAccessException newNoAccessException(MemberName name, Object from) {
- return newNoAccessException("cannot access", name, from);
- }
- public static IllegalAccessException newNoAccessException(String message,
- MemberName name, Object from) {
- message += ": " + name;
+ public IllegalAccessException makeAccessException(String message, Object from) {
+ message = message + ": "+ toString();
if (from != null) message += ", from " + from;
return new IllegalAccessException(message);
}
- public static ReflectiveOperationException newNoAccessException(MemberName name) {
- if (name.isResolved())
- return new IllegalAccessException(name.toString());
- else if (name.isConstructor())
- return new NoSuchMethodException(name.toString());
- else if (name.isMethod())
- return new NoSuchMethodException(name.toString());
+ public ReflectiveOperationException makeAccessException(String message) {
+ message = message + ": "+ toString();
+ if (isResolved())
+ return new IllegalAccessException(message);
+ else if (isConstructor())
+ return new NoSuchMethodException(message);
+ else if (isMethod())
+ return new NoSuchMethodException(message);
else
- return new NoSuchFieldException(name.toString());
- }
- public static Error uncaughtException(Exception ex) {
- Error err = new InternalError("uncaught exception");
- err.initCause(ex);
- return err;
+ return new NoSuchFieldException(message);
}
/** Actually making a query requires an access check. */
- public static Factory getFactory(Access token) {
- Access.check(token);
+ /*non-public*/ static Factory getFactory() {
return Factory.INSTANCE;
}
- public static Factory getFactory() {
- return getFactory(Access.getToken());
- }
/** A factory type for resolving member names with the help of the VM.
* TBD: Define access-safe public constructors for this factory.
*/
@@ -662,7 +641,7 @@ public final class MemberName implements Member, Cloneable {
MemberName result = resolveOrNull(m, searchSupers, lookupClass);
if (result != null)
return result;
- ReflectiveOperationException ex = newNoAccessException(m);
+ ReflectiveOperationException ex = m.makeAccessException("no access");
if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
throw nsmClass.cast(ex);
}
diff --git a/jdk/src/share/classes/java/dyn/MethodHandle.java b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java
similarity index 88%
rename from jdk/src/share/classes/java/dyn/MethodHandle.java
rename to jdk/src/share/classes/java/lang/invoke/MethodHandle.java
index b78b4024805..8165915c7bb 100644
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java
@@ -23,15 +23,10 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
-//import sun.dyn.*;
-import sun.dyn.Access;
-import sun.dyn.MethodHandleImpl;
-
-import static java.dyn.MethodHandles.invokers; // package-private API
-import static sun.dyn.MemberName.newIllegalArgumentException; // utility
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* A method handle is a typed, directly executable reference to an underlying method,
@@ -40,14 +35,8 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* These transformations are quite general, and include such patterns as
* {@linkplain #asType conversion},
* {@linkplain #bindTo insertion},
- * {@linkplain java.dyn.MethodHandles#dropArguments deletion},
- * and {@linkplain java.dyn.MethodHandles#filterArguments substitution}.
- *
- * Note: The super-class of MethodHandle is Object.
- * Any other super-class visible in the Reference Implementation
- * will be removed before the Proposed Final Draft.
- * Also, the final version will not include any public or
- * protected constructors.
+ * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
+ * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
*
*
Method handle contents
* Method handles are dynamically and strongly typed according to type descriptor.
@@ -56,7 +45,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* the method handle's own {@linkplain #type method type}.
*
* Every method handle reports its type via the {@link #type type} accessor.
- * This type descriptor is a {@link java.dyn.MethodType MethodType} object,
+ * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
* whose structure is a series of classes, one of which is
* the return type of the method (or {@code void.class} if none).
*
@@ -156,7 +145,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* This allows a more powerful negotiation of method type
* between caller and callee.
*
- * (Note: The adjusted method handle {@code M2} is not directly observable,
+ * (Note: The adjusted method handle {@code M2} is not directly observable,
* and implementations are therefore not required to materialize it.)
*
*
Invocation checking
@@ -204,11 +193,11 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* Java code can create a method handle that directly accesses
* any method, constructor, or field that is accessible to that code.
* This is done via a reflective, capability-based API called
- * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup}
+ * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
* For example, a static method handle can be obtained
- * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}.
+ * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
* There are also conversion methods from Core Reflection API objects,
- * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * such as {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
*
* Like classes and strings, method handles that correspond to accessible
* fields, methods, and constructors can also be represented directly
@@ -269,7 +258,7 @@ mh = mh.asType(mt);
x = mh.invokeExact((Object)1, (Object)2, (Object)3);
// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList(1,2,3)));
-// mt is { => int}
+// mt is int()
mt = MethodType.methodType(int.class);
mh = lookup.findVirtual(java.util.List.class, "size", mt);
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
@@ -325,15 +314,15 @@ mh.invokeExact(System.out, "Hello, world.");
*
* For the sake of tools (but not as a programming API), the signature polymorphic
* methods are marked with a private yet standard annotation,
- * {@code @java.dyn.MethodHandle.PolymorphicSignature}.
+ * {@code @java.lang.invoke.MethodHandle.PolymorphicSignature}.
* The annotation's retention is {@code RUNTIME}, so that all tools can see it.
*
*
Formal rules for processing signature polymorphic methods
*
* The following methods (and no others) are signature polymorphic:
*
- * {@link java.dyn.MethodHandle#invokeExact MethodHandle.invokeExact}
- * {@link java.dyn.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
+ * {@link java.lang.invoke.MethodHandle#invokeExact MethodHandle.invokeExact}
+ * {@link java.lang.invoke.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
*
*
* A signature polymorphic method will be declared with the following properties:
@@ -341,7 +330,7 @@ mh.invokeExact(System.out, "Hello, world.");
*
It must be native.
* It must take a single varargs parameter of the form {@code Object...}.
* It must produce a return value of type {@code Object}.
- * It must be contained within the {@code java.dyn} package.
+ * It must be contained within the {@code java.lang.invoke} package.
*
* Because of these requirements, a signature polymorphic method is able to accept
* any number and type of actual arguments, and can, with a cast, produce a value of any type.
@@ -354,7 +343,7 @@ mh.invokeExact(System.out, "Hello, world.");
*
* In an argument position of a method invocation on a signature polymorphic method,
* a null literal has type {@code java.lang.Void}, unless cast to a reference type.
- * (Note: This typing rule allows the null type to have its own encoding in linkage information
+ * (Note: This typing rule allows the null type to have its own encoding in linkage information
* distinct from other types.
*
* The linkage information for the return type is derived from a context-dependent target typing convention.
@@ -374,12 +363,12 @@ mh.invokeExact(System.out, "Hello, world.");
* and without implicit boxing or unboxing.
*
*
Interoperation between method handles and the Core Reflection API
- * Using factory methods in the {@link java.dyn.MethodHandles.Lookup Lookup} API,
+ * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
* any class member represented by a Core Reflection API object
* can be converted to a behaviorally equivalent method handle.
* For example, a reflective {@link java.lang.reflect.Method Method} can
* be converted to a method handle using
- * {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
* The resulting method handles generally provide more direct and efficient
* access to the underlying class members.
*
@@ -398,9 +387,9 @@ mh.invokeExact(System.out, "Hello, world.");
* they will throw {@code UnsupportedOperationException}.
*
* In order to obtain an invoker method for a particular type descriptor,
- * use {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker},
- * or {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
- * The {@link java.dyn.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
+ * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
+ * or {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
+ * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
* API is also able to return a method handle
* to call {@code invokeExact} or {@code invokeGeneric},
* for any specified type descriptor .
@@ -436,12 +425,35 @@ mh.invokeExact(System.out, "Hello, world.");
* @see MethodHandles
* @author John Rose, JSR 292 EG
*/
-public abstract class MethodHandle
- // Note: This is an implementation inheritance hack, and will be removed
- // with a JVM change which moves the required hidden state onto this class.
- extends MethodHandleImpl
-{
- private static Access IMPL_TOKEN = Access.getToken();
+public abstract class MethodHandle {
+ // { JVM internals:
+
+ private byte vmentry; // adapter stub or method entry point
+ //private int vmslots; // optionally, hoist type.form.vmslots
+ /*non-public*/ Object vmtarget; // VM-specific, class-specific target value
+
+ // TO DO: vmtarget should be invisible to Java, since the JVM puts internal
+ // managed pointers into it. Making it visible exposes it to debuggers,
+ // which can cause errors when they treat the pointer as an Object.
+
+ // These two dummy fields are present to force 'I' and 'J' signatures
+ // into this class's constant pool, so they can be transferred
+ // to vmentry when this class is loaded.
+ static final int INT_FIELD = 0;
+ static final long LONG_FIELD = 0;
+
+ // vmentry (a void* field) is used *only* by the JVM.
+ // The JVM adjusts its type to int or long depending on system wordsize.
+ // Since it is statically typed as neither int nor long, it is impossible
+ // to use this field from Java bytecode. (Please don't try to, either.)
+
+ // The vmentry is an assembly-language stub which is jumped to
+ // immediately after the method type is verified.
+ // For a direct MH, this stub loads the vmtarget's entry point
+ // and jumps to it.
+
+ // } End of JVM internals.
+
static { MethodHandleImpl.initStatics(); }
// interface MethodHandle
@@ -458,7 +470,7 @@ public abstract class MethodHandle
private MethodType type;
/**
- * Report the type of this method handle.
+ * Reports the type of this method handle.
* Every invocation of this method handle via {@code invokeExact} must exactly match this type.
* @return the method handle type
*/
@@ -467,39 +479,18 @@ public abstract class MethodHandle
}
/**
- * CONSTRUCTOR WILL BE REMOVED FOR PFD:
- * Temporary constructor in early versions of the Reference Implementation.
- * Method handle inheritance (if any) will be contained completely within
- * the {@code java.dyn} package.
+ * Package-private constructor for the method handle implementation hierarchy.
+ * Method handle inheritance will be contained completely within
+ * the {@code java.lang.invoke} package.
*/
- // The constructor for MethodHandle may only be called by privileged code.
- // Subclasses may be in other packages, but must possess
- // a token which they obtained from MH with a security check.
- // @param token non-null object which proves access permission
// @param type type (permanently assigned) of the new method handle
- protected MethodHandle(Access token, MethodType type) {
- super(token);
- Access.check(token);
- this.type = type;
- }
-
- private void initType(MethodType type) {
+ /*non-public*/ MethodHandle(MethodType type) {
type.getClass(); // elicit NPE
- if (this.type != null) throw new InternalError();
this.type = type;
}
- static {
- // This hack allows the implementation package special access to
- // the internals of MethodHandle. In particular, the MTImpl has all sorts
- // of cached information useful to the implementation code.
- MethodHandleImpl.setMethodHandleFriend(IMPL_TOKEN, new MethodHandleImpl.MethodHandleFriend() {
- public void initType(MethodHandle mh, MethodType type) { mh.initType(type); }
- });
- }
-
/**
- * Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match.
+ * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
* The type descriptor at the call site of {@code invokeExact} must
* exactly match this method handle's {@link #type type}.
* No conversions are allowed on arguments or return values.
@@ -508,7 +499,7 @@ public abstract class MethodHandle
* it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
- * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
+ * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
@@ -516,7 +507,7 @@ public abstract class MethodHandle
public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
/**
- * Invoke the method handle, allowing any caller type descriptor,
+ * Invokes the method handle, allowing any caller type descriptor,
* and optionally performing conversions on arguments and return values.
*
* If the call site type descriptor exactly matches this method handle's {@link #type type},
@@ -542,7 +533,7 @@ public abstract class MethodHandle
* it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
- * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
+ * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
@@ -551,7 +542,7 @@ public abstract class MethodHandle
public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
/**
- * Perform a varargs invocation, passing the arguments in the given array
+ * Performs a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
* which mentions only the type {@code Object}, and whose arity is the length
* of the argument array.
@@ -608,7 +599,7 @@ public abstract class MethodHandle
return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
}
if (argc <= 10) {
- MethodHandle invoker = invokers(type).genericInvoker();
+ MethodHandle invoker = type.invokers().genericInvoker();
switch (argc) {
case 0: return invoker.invokeExact(this);
case 1: return invoker.invokeExact(this,
@@ -647,17 +638,34 @@ public abstract class MethodHandle
}
// more than ten arguments get boxed in a varargs list:
- MethodHandle invoker = invokers(type).spreadInvoker(0);
+ MethodHandle invoker = type.invokers().spreadInvoker(0);
return invoker.invokeExact(this, arguments);
}
- /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
+
+ /**
+ * Performs a varargs invocation, passing the arguments in the given array
+ * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
+ * which mentions only the type {@code Object}, and whose arity is the length
+ * of the argument array.
+ *
+ * This method is also equivalent to the following code:
+ *
+ * {@link #invokeWithArguments(Object...) invokeWithArguments}(arguments.toArray())
+ *
+ *
+ * @param arguments the arguments to pass to the target
+ * @return the result returned by the target
+ * @throws ClassCastException if an argument cannot be converted by reference casting
+ * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
+ * @throws Throwable anything thrown by the target method invocation
+ */
public Object invokeWithArguments(java.util.List> arguments) throws Throwable {
return invokeWithArguments(arguments.toArray());
}
/**
- * Produce an adapter method handle which adapts the type of the
- * current method handle to a new type
+ * Produces an adapter method handle which adapts the type of the
+ * current method handle to a new type.
* The resulting method handle is guaranteed to report a type
* which is equal to the desired new type.
*
@@ -685,7 +693,7 @@ public abstract class MethodHandle
}
/**
- * Make an adapter which accepts a trailing array argument
+ * Makes an adapter which accepts a trailing array argument
* and spreads its elements as positional arguments.
* The new method handle adapts, as its target ,
* the current method handle. The type of the adapter will be
@@ -733,7 +741,7 @@ public abstract class MethodHandle
}
/**
- * Make an adapter which accepts a given number of trailing
+ * Makes an adapter which accepts a given number of trailing
* positional arguments and collects them into an array argument.
* The new method handle adapts, as its target ,
* the current method handle. The type of the adapter will be
@@ -784,7 +792,7 @@ public abstract class MethodHandle
}
/**
- * Make a variable arity adapter which is able to accept
+ * Makes a variable arity adapter which is able to accept
* any number of trailing positional arguments and collect them
* into an array argument.
*
@@ -942,12 +950,12 @@ assert(failed);
}
/**
- * Determine if this method handle
+ * Determines if this method handle
* supports {@linkplain #asVarargsCollector variable arity} calls.
* Such method handles arise from the following sources:
*
* a call to {@linkplain #asVarargsCollector asVarargsCollector}
- * a call to a {@linkplain java.dyn.MethodHandles.Lookup lookup method}
+ * a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
* which resolves to a variable arity Java method or constructor
* an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
* which resolves to a variable arity Java method or constructor
@@ -960,9 +968,9 @@ assert(failed);
}
/**
- * Bind a value {@code x} to the first argument of a method handle, without invoking it.
+ * Binds a value {@code x} to the first argument of a method handle, without invoking it.
* The new method handle adapts, as its target ,
- * to the current method handle.
+ * the current method handle by binding it to the given argument.
* The type of the bound handle will be
* the same as the type of the target, except that a single leading
* reference parameter will be omitted.
@@ -974,9 +982,12 @@ assert(failed);
*
* The reference {@code x} must be convertible to the first parameter
* type of the target.
+ *
+ * (Note: Because method handles are immutable, the target method handle
+ * retains its original type and behavior.)
* @param x the value to bind to the first argument of the target
- * @return a new method handle which collects some trailing argument
- * into an array, before calling the original method handle
+ * @return a new method handle which prepends the given value to the incoming
+ * argument list, before calling the original method handle
* @throws IllegalArgumentException if the target does not have a
* leading parameter type that is a reference type
* @throws ClassCastException if {@code x} cannot be converted
@@ -984,7 +995,15 @@ assert(failed);
* @see MethodHandles#insertArguments
*/
public MethodHandle bindTo(Object x) {
- return MethodHandles.insertArguments(this, 0, x);
+ Class> ptype;
+ if (type().parameterCount() == 0 ||
+ (ptype = type().parameterType(0)).isPrimitive())
+ throw newIllegalArgumentException("no leading reference parameter", x);
+ x = MethodHandles.checkValue(ptype, x);
+ // Cf. MethodHandles.insertArguments for the following logic:
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(this, x);
+ if (bmh != null) return bmh;
+ return MethodHandleImpl.bindArgument(this, 0, x);
}
/**
@@ -996,14 +1015,14 @@ assert(failed);
* "MethodHandle" + type().toString()
*
*
- * Note: Future releases of this API may add further information
+ * (Note: Future releases of this API may add further information
* to the string representation.
- * Therefore, the present syntax should not be parsed by applications.
+ * Therefore, the present syntax should not be parsed by applications.)
*
* @return a string representation of the method handle
*/
@Override
public String toString() {
- return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
+ return getNameString(this);
}
}
diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
similarity index 78%
rename from jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
rename to jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
index eab4923540e..e82442092fe 100644
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -23,136 +23,36 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import sun.dyn.util.VerifyType;
+import sun.invoke.util.VerifyType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
-import sun.dyn.empty.Empty;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
+import sun.invoke.empty.Empty;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
import sun.misc.Unsafe;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MemberName.newNoAccessException;
-import static sun.dyn.MemberName.uncaughtException;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
- * Base class for method handles, containing JVM-specific fields and logic.
- * TO DO: It should not be a base class.
+ * Trusted implementation code for MethodHandle.
* @author jrose
*/
-public abstract class MethodHandleImpl {
-
- // Fields which really belong in MethodHandle:
- private byte vmentry; // adapter stub or method entry point
- //private int vmslots; // optionally, hoist type.form.vmslots
- protected Object vmtarget; // VM-specific, class-specific target value
- //MethodType type; // defined in MethodHandle
-
- // TO DO: vmtarget should be invisible to Java, since the JVM puts internal
- // managed pointers into it. Making it visible exposes it to debuggers,
- // which can cause errors when they treat the pointer as an Object.
-
- // These two dummy fields are present to force 'I' and 'J' signatures
- // into this class's constant pool, so they can be transferred
- // to vmentry when this class is loaded.
- static final int INT_FIELD = 0;
- static final long LONG_FIELD = 0;
-
- /** Access methods for the internals of MethodHandle, supplied to
- * MethodHandleImpl as a trusted agent.
- */
- static public interface MethodHandleFriend {
- void initType(MethodHandle mh, MethodType type);
- }
- public static void setMethodHandleFriend(Access token, MethodHandleFriend am) {
- Access.check(token);
- if (METHOD_HANDLE_FRIEND != null)
- throw new InternalError(); // just once
- METHOD_HANDLE_FRIEND = am;
- }
- static private MethodHandleFriend METHOD_HANDLE_FRIEND;
-
- // NOT public
- static void initType(MethodHandle mh, MethodType type) {
- METHOD_HANDLE_FRIEND.initType(mh, type);
- }
-
- // type is defined in java.dyn.MethodHandle, which is platform-independent
-
- // vmentry (a void* field) is used *only* by by the JVM.
- // The JVM adjusts its type to int or long depending on system wordsize.
- // Since it is statically typed as neither int nor long, it is impossible
- // to use this field from Java bytecode. (Please don't try to, either.)
-
- // The vmentry is an assembly-language stub which is jumped to
- // immediately after the method type is verified.
- // For a direct MH, this stub loads the vmtarget's entry point
- // and jumps to it.
-
- /**
- * VM-based method handles must have a security token.
- * This security token can only be obtained by trusted code.
- * Do not create method handles directly; use factory methods.
- */
- public MethodHandleImpl(Access token) {
- Access.check(token);
- }
-
- /** Initialize the method type form to participate in JVM calls.
- * This is done once for each erased type.
- */
- public static void init(Access token, MethodType self) {
- Access.check(token);
- if (MethodHandleNatives.JVM_SUPPORT)
- MethodHandleNatives.init(self);
- }
-
+/*non-public*/ abstract class MethodHandleImpl {
/// Factory methods to create method handles:
private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
- static private Lookup IMPL_LOOKUP_INIT;
-
- public static void initLookup(Access token, Lookup lookup) {
- Access.check(token);
- if (IMPL_LOOKUP_INIT != null)
- throw new InternalError();
- IMPL_LOOKUP_INIT = lookup;
- }
-
- public static Lookup getLookup(Access token) {
- Access.check(token);
- return IMPL_LOOKUP;
- }
-
- static {
- if (!MethodHandleNatives.JVM_SUPPORT) // force init of native API
- throw new InternalError("No JVM support for JSR 292");
- // Force initialization of Lookup, so it calls us back as initLookup:
- MethodHandles.publicLookup();
- if (IMPL_LOOKUP_INIT == null)
- throw new InternalError();
- }
-
- public static void initStatics() {
+ static void initStatics() {
// Trigger preceding sequence.
}
- /** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
- static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT;
-
-
/** Look up a given method.
- * Callable only from java.dyn and related packages.
+ * Callable only from sun.invoke and related packages.
*
* The resulting method handle type will be of the given type,
* with a receiver type {@code rcvc} prepended if the member is not static.
@@ -170,10 +70,9 @@ public abstract class MethodHandleImpl {
* @return a direct handle to the matching method
* @throws IllegalAccessException if the given method cannot be accessed by the lookup class
*/
- public static
- MethodHandle findMethod(Access token, MemberName method,
+ static
+ MethodHandle findMethod(MemberName method,
boolean doDispatch, Class> lookupClass) throws IllegalAccessException {
- Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType();
if (!method.isStatic()) {
// adjust the advertised receiver type to be exactly the one requested
@@ -183,7 +82,7 @@ public abstract class MethodHandleImpl {
}
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid())
- throw newNoAccessException(method, lookupClass);
+ throw method.makeAccessException("no access", lookupClass);
assert(mh.type() == mtype);
if (!method.isVarargs())
return mh;
@@ -191,13 +90,12 @@ public abstract class MethodHandleImpl {
return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
}
- public static
- MethodHandle makeAllocator(Access token, MethodHandle rawConstructor) {
- Access.check(token);
+ static
+ MethodHandle makeAllocator(MethodHandle rawConstructor) {
MethodType rawConType = rawConstructor.type();
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
MethodHandle allocator
- = AllocateObject.make(token, rawConType.parameterType(0), rawConstructor);
+ = AllocateObject.make(rawConType.parameterType(0), rawConstructor);
assert(allocator.type()
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
return allocator;
@@ -211,13 +109,11 @@ public abstract class MethodHandleImpl {
private AllocateObject(MethodHandle invoker,
Class allocateClass, MethodHandle rawConstructor) {
- super(Access.TOKEN, invoker);
+ super(invoker);
this.allocateClass = allocateClass;
this.rawConstructor = rawConstructor;
}
- static MethodHandle make(Access token,
- Class> allocateClass, MethodHandle rawConstructor) {
- Access.check(token);
+ static MethodHandle make(Class> allocateClass, MethodHandle rawConstructor) {
MethodType rawConType = rawConstructor.type();
assert(rawConType.parameterType(0) == allocateClass);
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
@@ -225,18 +121,18 @@ public abstract class MethodHandleImpl {
if (nargs < INVOKES.length) {
MethodHandle invoke = INVOKES[nargs];
MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = convertArguments(token, rawConstructor, conType, rawConType, null);
+ MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, null);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
assert(galloc.type() == newType.generic());
- return convertArguments(token, galloc, newType, galloc.type(), null);
+ return convertArguments(galloc, newType, galloc.type(), null);
} else {
MethodHandle invoke = VARARGS_INVOKE;
MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = spreadArguments(token, rawConstructor, conType, 1);
+ MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
- return collectArguments(token, galloc, newType, 1, null);
+ return collectArguments(galloc, newType, 1, null);
}
}
@Override
@@ -338,20 +234,16 @@ public abstract class MethodHandleImpl {
}
}
- public static
- MethodHandle accessField(Access token,
- MemberName member, boolean isSetter,
+ static
+ MethodHandle accessField(MemberName member, boolean isSetter,
Class> lookupClass) {
- Access.check(token);
// Use sun. misc.Unsafe to dig up the dirt on the field.
- MethodHandle mh = new FieldAccessor(token, member, isSetter);
+ MethodHandle mh = new FieldAccessor(member, isSetter);
return mh;
}
- public static
- MethodHandle accessArrayElement(Access token,
- Class> arrayClass, boolean isSetter) {
- Access.check(token);
+ static
+ MethodHandle accessArrayElement(Class> arrayClass, boolean isSetter) {
if (!arrayClass.isArray())
throw newIllegalArgumentException("not an array: "+arrayClass);
Class> elemClass = arrayClass.getComponentType();
@@ -379,12 +271,13 @@ public abstract class MethodHandleImpl {
final long offset;
final String name;
- public FieldAccessor(Access token, MemberName field, boolean isSetter) {
- super(Access.TOKEN, fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
- this.offset = (long) field.getVMIndex(token);
+ FieldAccessor(MemberName field, boolean isSetter) {
+ super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
+ this.offset = (long) field.getVMIndex();
this.name = field.getName();
this.base = staticBase(field);
}
+ @Override
public String toString() { return addTypeString(name, this); }
int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
@@ -560,10 +453,8 @@ public abstract class MethodHandleImpl {
* @param receiver Receiver (or first static method argument) to pre-bind.
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
*/
- public static
- MethodHandle bindReceiver(Access token,
- MethodHandle target, Object receiver) {
- Access.check(token);
+ static
+ MethodHandle bindReceiver(MethodHandle target, Object receiver) {
if (target instanceof AdapterMethodHandle &&
((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
) {
@@ -574,7 +465,7 @@ public abstract class MethodHandleImpl {
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
MethodType newType = target.type().dropParameterTypes(0, 1);
- return convertArguments(token, bmh, newType, bmh.type(), null);
+ return convertArguments(bmh, newType, bmh.type(), null);
}
}
}
@@ -590,19 +481,15 @@ public abstract class MethodHandleImpl {
* @param receiver Argument (which can be a boxed primitive) to pre-bind.
* @return a suitable BoundMethodHandle
*/
- public static
- MethodHandle bindArgument(Access token,
- MethodHandle target, int argnum, Object receiver) {
- Access.check(token);
+ static
+ MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) {
return new BoundMethodHandle(target, receiver, argnum);
}
- public static MethodHandle convertArguments(Access token,
- MethodHandle target,
+ static MethodHandle convertArguments(MethodHandle target,
MethodType newType,
MethodType oldType,
int[] permutationOrNull) {
- Access.check(token);
assert(oldType.parameterCount() == target.type().parameterCount());
if (permutationOrNull != null) {
int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
@@ -613,7 +500,7 @@ public abstract class MethodHandleImpl {
for (int i = 0; i < outargs; i++)
callTypeArgs[i] = newType.parameterType(permutationOrNull[i]);
MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs);
- target = convertArguments(token, target, callType, oldType, null);
+ target = convertArguments(target, callType, oldType, null);
assert(target != null);
oldType = target.type();
List goal = new ArrayList(); // i*TOKEN
@@ -710,7 +597,7 @@ public abstract class MethodHandleImpl {
Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
MethodHandle nextTarget
- = AdapterMethodHandle.makeRotateArguments(token, rotType, target,
+ = AdapterMethodHandle.makeRotateArguments(rotType, target,
rotBeg, rotSpan.size(), rotBy);
if (nextTarget != null) {
//System.out.println("Rot: "+rotSpan+" by "+rotBy);
@@ -733,7 +620,7 @@ public abstract class MethodHandleImpl {
int j = state.indexOf(arg);
Collections.swap(ptypes, i, j);
MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeSwapArguments(token, swapType, target, i, j);
+ target = AdapterMethodHandle.makeSwapArguments(swapType, target, i, j);
if (target == null) throw newIllegalArgumentException("cannot swap");
assert(target.type() == swapType);
oldType = swapType;
@@ -760,7 +647,7 @@ public abstract class MethodHandleImpl {
List> ptypes = oldType.parameterList();
ptypes = ptypes.subList(0, ptypes.size() - dupArgCount);
MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeDupArguments(token, dupType, target, dupArgPos, dupArgCount);
+ target = AdapterMethodHandle.makeDupArguments(dupType, target, dupArgPos, dupArgCount);
if (target == null)
throw newIllegalArgumentException("cannot dup");
oldType = target.type();
@@ -778,7 +665,7 @@ public abstract class MethodHandleImpl {
List> dropTypes = newType.parameterList()
.subList(dropArgPos, dropArgPos + dropArgCount);
MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
- target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount);
+ target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
if (target == null) throw newIllegalArgumentException("cannot drop");
oldType = target.type();
}
@@ -787,7 +674,7 @@ public abstract class MethodHandleImpl {
return target;
if (oldType.parameterCount() != newType.parameterCount())
throw newIllegalArgumentException("mismatched parameter count");
- MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
+ MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target);
if (res != null)
return res;
int argc = oldType.parameterCount();
@@ -797,26 +684,24 @@ public abstract class MethodHandleImpl {
// then back to the desired types. We might have to use Java-based
// method handles to do this.
MethodType objType = MethodType.genericMethodType(argc);
- MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
+ MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target);
if (objTarget == null)
objTarget = FromGeneric.make(target);
- res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget);
+ res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget);
if (res != null)
return res;
return ToGeneric.make(newType, objTarget);
}
- public static MethodHandle spreadArguments(Access token,
- MethodHandle target,
+ static MethodHandle spreadArguments(MethodHandle target,
MethodType newType,
int spreadArg) {
- Access.check(token);
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
MethodType oldType = target.type();
// spread the last argument of newType to oldType
int spreadCount = oldType.parameterCount() - spreadArg;
Class spreadArgType = Object[].class;
- MethodHandle res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount);
+ MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, spreadArgType, spreadArg, spreadCount);
if (res != null)
return res;
// try an intermediate adapter
@@ -829,20 +714,19 @@ public abstract class MethodHandleImpl {
ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
// after spreading, some arguments may need further conversion
- MethodHandle target2 = convertArguments(token, target, midType, oldType, null);
+ MethodHandle target2 = convertArguments(target, midType, oldType, null);
if (target2 == null)
throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
- res = AdapterMethodHandle.makeSpreadArguments(token, newType, target2, spreadArgType, spreadArg, spreadCount);
+ res = AdapterMethodHandle.makeSpreadArguments(newType, target2, spreadArgType, spreadArg, spreadCount);
if (res != null)
return res;
res = SpreadGeneric.make(target2, spreadCount);
if (res != null)
- res = convertArguments(token, res, newType, res.type(), null);
+ res = convertArguments(res, newType, res.type(), null);
return res;
}
- public static MethodHandle collectArguments(Access token,
- MethodHandle target,
+ static MethodHandle collectArguments(MethodHandle target,
MethodType newType,
int collectArg,
MethodHandle collector) {
@@ -856,29 +740,27 @@ public abstract class MethodHandleImpl {
// oldType // (a..., b...)=>r
assert(newType.parameterCount() == collectArg + colType.parameterCount());
assert(oldType.parameterCount() == collectArg + 1);
- MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
- MethodHandle gcollector = convertArguments(token, collector, colType.generic(), colType, null);
+ MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
+ MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, null);
if (gtarget == null || gcollector == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
- MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
+ MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
return result;
}
- public static MethodHandle filterArgument(Access token,
- MethodHandle target,
+ static MethodHandle filterArgument(MethodHandle target,
int pos,
MethodHandle filter) {
- Access.check(token);
MethodType ttype = target.type(), gttype = ttype.generic();
if (ttype != gttype) {
- target = convertArguments(token, target, gttype, ttype, null);
+ target = convertArguments(target, gttype, ttype, null);
ttype = gttype;
}
MethodType ftype = filter.type(), gftype = ftype.generic();
if (ftype.parameterCount() != 1)
throw new InternalError();
if (ftype != gftype) {
- filter = convertArguments(token, filter, gftype, ftype, null);
+ filter = convertArguments(filter, gftype, ftype, null);
ftype = gftype;
}
if (ftype == ttype) {
@@ -888,27 +770,24 @@ public abstract class MethodHandleImpl {
return FilterGeneric.makeArgumentFilter(pos, filter, target);
}
- public static MethodHandle foldArguments(Access token,
- MethodHandle target,
+ static MethodHandle foldArguments(MethodHandle target,
MethodType newType,
MethodHandle combiner) {
- Access.check(token);
MethodType oldType = target.type();
MethodType ctype = combiner.type();
- MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
- MethodHandle gcombiner = convertArguments(token, combiner, ctype.generic(), ctype, null);
+ MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
+ MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, null);
if (gtarget == null || gcombiner == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
- MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
+ MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
return result;
}
- public static
- MethodHandle dropArguments(Access token, MethodHandle target,
+ static
+ MethodHandle dropArguments(MethodHandle target,
MethodType newType, int argnum) {
- Access.check(token);
int drops = newType.parameterCount() - target.type().parameterCount();
- MethodHandle res = AdapterMethodHandle.makeDropArguments(token, newType, target, argnum, drops);
+ MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
if (res != null)
return res;
throw new UnsupportedOperationException("NYI");
@@ -918,36 +797,34 @@ public abstract class MethodHandleImpl {
private final MethodHandle test, target, fallback;
private GuardWithTest(MethodHandle invoker,
MethodHandle test, MethodHandle target, MethodHandle fallback) {
- super(Access.TOKEN, invoker);
+ super(invoker);
this.test = test;
this.target = target;
this.fallback = fallback;
}
- static MethodHandle make(Access token,
- MethodHandle test, MethodHandle target, MethodHandle fallback) {
- Access.check(token);
+ static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
MethodType type = target.type();
int nargs = type.parameterCount();
if (nargs < INVOKES.length) {
MethodHandle invoke = INVOKES[nargs];
MethodType gtype = type.generic();
assert(invoke.type().dropParameterTypes(0,1) == gtype);
- MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null);
- MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
- MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null);
+ MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), null);
+ MethodHandle gtarget = convertArguments(target, gtype, type, null);
+ MethodHandle gfallback = convertArguments(fallback, gtype, type, null);
if (gtest == null || gtarget == null || gfallback == null) return null;
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
- return convertArguments(token, gguard, type, gtype, null);
+ return convertArguments(gguard, type, gtype, null);
} else {
MethodHandle invoke = VARARGS_INVOKE;
MethodType gtype = MethodType.genericMethodType(1);
assert(invoke.type().dropParameterTypes(0,1) == gtype);
- MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0);
- MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
- MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0);
+ MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0);
+ MethodHandle gtarget = spreadArguments(target, gtype, 0);
+ MethodHandle gfallback = spreadArguments(fallback, gtype, 0);
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
if (gtest == null || gtarget == null || gfallback == null) return null;
- return collectArguments(token, gguard, type, 0, null);
+ return collectArguments(gguard, type, 0, null);
}
}
@Override
@@ -1034,24 +911,23 @@ public abstract class MethodHandleImpl {
}
}
- public static
- MethodHandle makeGuardWithTest(Access token,
- MethodHandle test,
+ static
+ MethodHandle makeGuardWithTest(MethodHandle test,
MethodHandle target,
MethodHandle fallback) {
- return GuardWithTest.make(token, test, target, fallback);
+ return GuardWithTest.make(test, target, fallback);
}
private static class GuardWithCatch extends BoundMethodHandle {
private final MethodHandle target;
private final Class extends Throwable> exType;
private final MethodHandle catcher;
- public GuardWithCatch(MethodHandle target, Class extends Throwable> exType, MethodHandle catcher) {
+ GuardWithCatch(MethodHandle target, Class extends Throwable> exType, MethodHandle catcher) {
this(INVOKES[target.type().parameterCount()], target, exType, catcher);
}
- public GuardWithCatch(MethodHandle invoker,
- MethodHandle target, Class extends Throwable> exType, MethodHandle catcher) {
- super(Access.TOKEN, invoker);
+ GuardWithCatch(MethodHandle invoker,
+ MethodHandle target, Class extends Throwable> exType, MethodHandle catcher) {
+ super(invoker);
this.target = target;
this.exType = exType;
this.catcher = catcher;
@@ -1171,42 +1047,40 @@ public abstract class MethodHandleImpl {
}
- public static
- MethodHandle makeGuardWithCatch(Access token,
- MethodHandle target,
+ static
+ MethodHandle makeGuardWithCatch(MethodHandle target,
Class extends Throwable> exType,
MethodHandle catcher) {
- Access.check(token);
MethodType type = target.type();
MethodType ctype = catcher.type();
int nargs = type.parameterCount();
if (nargs < GuardWithCatch.INVOKES.length) {
MethodType gtype = type.generic();
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
- MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
- MethodHandle gcatcher = convertArguments(token, catcher, gcatchType, ctype, null);
+ MethodHandle gtarget = convertArguments(target, gtype, type, null);
+ MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, null);
MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null;
- return convertArguments(token, gguard, type, gtype, null);
+ return convertArguments(gguard, type, gtype, null);
} else {
MethodType gtype = MethodType.genericMethodType(0, true);
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
- MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
- MethodHandle gcatcher = spreadArguments(token, catcher, gcatchType, 1);
+ MethodHandle gtarget = spreadArguments(target, gtype, 0);
+ MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1);
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null;
- return collectArguments(token, gguard, type, 0, null);
+ return collectArguments(gguard, type, 0, null);
}
}
- public static
- MethodHandle throwException(Access token, MethodType type) {
- Access.check(token);
- return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
+ static
+ MethodHandle throwException(MethodType type) {
+ return AdapterMethodHandle.makeRetypeRaw(type, throwException());
}
- static final MethodHandle THROW_EXCEPTION;
- static {
+ static MethodHandle THROW_EXCEPTION;
+ static MethodHandle throwException() {
+ if (THROW_EXCEPTION != null) return THROW_EXCEPTION;
try {
THROW_EXCEPTION
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
@@ -1214,71 +1088,19 @@ public abstract class MethodHandleImpl {
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
+ return THROW_EXCEPTION;
}
static Empty throwException(T t) throws T { throw t; }
- public static String getNameString(Access token, MethodHandle target, Object type) {
- Access.check(token);
- if (!(type instanceof MethodType)) {
- if (type == null)
- type = target.type();
- else if (type instanceof MethodHandle)
- type = ((MethodHandle)type).type();
- }
- MemberName name = null;
- if (target != null)
- name = MethodHandleNatives.getMethodName(target);
- if (name == null)
- return "invoke" + type;
- return name.getName() + type;
- }
-
- public static String getNameString(Access token, MethodHandle target) {
- return getNameString(token, target, null);
- }
-
- static String addTypeString(Object obj, MethodHandle target) {
- String str = String.valueOf(obj);
- if (target == null) return str;
- int paren = str.indexOf('(');
- if (paren >= 0) str = str.substring(0, paren);
- return str + target.type();
- }
-
- static void checkSpreadArgument(Object av, int n) {
- if (av == null ? n != 0 : ((Object[])av).length != n)
- throw newIllegalArgumentException("Array is not of length "+n);
- }
-
- static void raiseException(int code, Object actual, Object required) {
- String message;
- // disregard the identity of the actual object, if it is not a class:
- if (!(actual instanceof Class) && !(actual instanceof MethodType))
- actual = actual.getClass();
- if (actual != null)
- message = "required "+required+" but encountered "+actual;
- else
- message = "required "+required;
- switch (code) {
- case 192: // checkcast
- throw new ClassCastException(message);
- default:
- throw new InternalError("unexpected code "+code+": "+message);
- }
- }
-
// Linkage support:
- public static void registerBootstrap(Access token, Class> callerClass, MethodHandle bootstrapMethod) {
- Access.check(token);
+ static void registerBootstrap(Class> callerClass, MethodHandle bootstrapMethod) {
MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
}
- public static MethodHandle getBootstrap(Access token, Class> callerClass) {
- Access.check(token);
+ static MethodHandle getBootstrap(Class> callerClass) {
return MethodHandleNatives.getBootstrap(callerClass);
}
- public static MethodHandle asVarargsCollector(Access token, MethodHandle target, Class> arrayType) {
- Access.check(token);
- return AdapterMethodHandle.makeVarargsCollector(token, target, arrayType);
+ static MethodHandle asVarargsCollector(MethodHandle target, Class> arrayType) {
+ return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
}
}
diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
similarity index 89%
rename from jdk/src/share/classes/sun/dyn/MethodHandleNatives.java
rename to jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
index 5f1076bff6a..82d5d898638 100644
--- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,14 +23,13 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
-import static sun.dyn.MethodHandleNatives.Constants.*;
-import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* The JVM interface for the method handles package is all here.
@@ -81,14 +80,12 @@ class MethodHandleNatives {
* This routine is for debugging and reflection.
*/
static MemberName getMethodName(MethodHandle self) {
- if (!JVM_SUPPORT) return null;
return (MemberName) getTarget(self, ETF_METHOD_NAME);
}
/** Fetch the reflective version of the handled method, if available.
*/
static AccessibleObject getTargetMethod(MethodHandle self) {
- if (!JVM_SUPPORT) return null;
return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
}
@@ -97,7 +94,6 @@ class MethodHandleNatives {
* If it is chained to another method handle, return that handle.
*/
static Object getTargetInfo(MethodHandle self) {
- if (!JVM_SUPPORT) return null;
return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
}
@@ -111,11 +107,6 @@ class MethodHandleNatives {
*/
static native int getConstant(int which);
- /** True iff this HotSpot JVM has built-in support for method handles.
- * If false, some test cases might run, but functionality will be missing.
- */
- public static final boolean JVM_SUPPORT;
-
/** Java copy of MethodHandlePushLimit in range 2..255. */
static final int JVM_PUSH_LIMIT;
/** JVM stack motion (in words) after one slot is pushed, usually -1.
@@ -127,31 +118,24 @@ class MethodHandleNatives {
private static native void registerNatives();
static {
- boolean JVM_SUPPORT_;
int JVM_PUSH_LIMIT_;
int JVM_STACK_MOVE_UNIT_;
int CONV_OP_IMPLEMENTED_MASK_;
try {
registerNatives();
- JVM_SUPPORT_ = true;
JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
} catch (UnsatisfiedLinkError ee) {
// ignore; if we use init() methods later we'll see linkage errors
- JVM_SUPPORT_ = false;
JVM_PUSH_LIMIT_ = 3; // arbitrary
JVM_STACK_MOVE_UNIT_ = -1; // arbitrary
CONV_OP_IMPLEMENTED_MASK_ = 0;
- //System.out.println("Warning: Running with JVM_SUPPORT=false");
- //System.out.println(ee);
- JVM_SUPPORT = JVM_SUPPORT_;
JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
throw ee; // just die; hopeless to try to run with an older JVM
}
- JVM_SUPPORT = JVM_SUPPORT_;
JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
if (CONV_OP_IMPLEMENTED_MASK_ == 0)
@@ -189,9 +173,15 @@ class MethodHandleNatives {
MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
VM_INDEX_UNINITIALIZED = -99;
+ // BoundMethodHandle
+ /** Constants for decoding the vmargslot field, which contains 2 values. */
+ static final int
+ ARG_SLOT_PUSH_SHIFT = 16,
+ ARG_SLOT_MASK = (1< rtype, Class>[] ptypes) {
- MethodType.genericMethodType(0); // trigger initialization
- return MethodTypeImpl.makeImpl(Access.TOKEN, rtype, ptypes, true);
+ return MethodType.makeImpl(rtype, ptypes, true);
}
/**
* The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning.
*/
static void notifyGenericMethodType(MethodType type) {
- try {
- // Trigger adapter creation.
- InvokeGeneric.genericInvokerOf(type);
- } catch (Exception ex) {
- Error err = new InternalError("Exception while resolving invokeGeneric");
- err.initCause(ex);
- throw err;
+ type.form().notifyGenericMethodType();
+ }
+
+ /**
+ * The JVM wants to raise an exception. Here's the path.
+ */
+ static void raiseException(int code, Object actual, Object required) {
+ String message;
+ // disregard the identity of the actual object, if it is not a class:
+ if (!(actual instanceof Class) && !(actual instanceof MethodType))
+ actual = actual.getClass();
+ if (actual != null)
+ message = "required "+required+" but encountered "+actual;
+ else
+ message = "required "+required;
+ switch (code) {
+ case 192: // checkcast
+ throw new ClassCastException(message);
+ default:
+ throw new InternalError("unexpected code "+code+": "+message);
}
}
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java
new file mode 100644
index 00000000000..6ea8f978b63
--- /dev/null
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, 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.lang.invoke;
+
+/**
+ * This class consists exclusively of static names internal to the
+ * method handle implementation.
+ * Usage: {@code import static java.lang.invoke.MethodHandleStatics.*}
+ * @author John Rose, JSR 292 EG
+ */
+/*non-public*/ class MethodHandleStatics {
+
+ private MethodHandleStatics() { } // do not instantiate
+
+ /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
+ if (type == null)
+ type = target.type();
+ MemberName name = null;
+ if (target != null)
+ name = MethodHandleNatives.getMethodName(target);
+ if (name == null)
+ return "invoke" + type;
+ return name.getName() + type;
+ }
+
+ /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
+ return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
+ }
+
+ /*non-public*/ static String getNameString(MethodHandle target) {
+ return getNameString(target, (MethodType) null);
+ }
+
+ /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
+ String str = String.valueOf(obj);
+ if (target == null) return str;
+ int paren = str.indexOf('(');
+ if (paren >= 0) str = str.substring(0, paren);
+ return str + target.type();
+ }
+
+ static void checkSpreadArgument(Object av, int n) {
+ if (av == null ? n != 0 : ((Object[])av).length != n)
+ throw newIllegalArgumentException("Array is not of length "+n);
+ }
+
+ // handy shared exception makers (they simplify the common case code)
+ /*non-public*/ static RuntimeException newIllegalStateException(String message) {
+ return new IllegalStateException(message);
+ }
+ /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
+ return new IllegalStateException(message(message, obj));
+ }
+ /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
+ return new IllegalArgumentException(message);
+ }
+ /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
+ return new IllegalArgumentException(message(message, obj));
+ }
+ /*non-public*/ static Error uncaughtException(Exception ex) {
+ Error err = new InternalError("uncaught exception");
+ err.initCause(ex);
+ return err;
+ }
+ private static String message(String message, Object obj) {
+ if (obj != null) message = message + ": " + obj;
+ return message;
+ }
+}
diff --git a/jdk/src/share/classes/java/dyn/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
similarity index 90%
rename from jdk/src/share/classes/java/dyn/MethodHandles.java
rename to jdk/src/share/classes/java/lang/invoke/MethodHandles.java
index 3bc9bd4a327..12e36da623a 100644
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
@@ -23,24 +23,18 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
import java.lang.reflect.*;
-import sun.dyn.Access;
-import sun.dyn.MemberName;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.WrapperInstance;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.VerifyAccess;
-import sun.dyn.util.Wrapper;
+import sun.invoke.WrapperInstance;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
-import sun.dyn.Invokers;
-import sun.dyn.MethodTypeImpl;
import sun.reflect.Reflection;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MemberName.newNoAccessException;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* This class consists exclusively of static methods that operate on or return
@@ -49,7 +43,7 @@ import static sun.dyn.MemberName.newNoAccessException;
* Lookup methods which help create method handles for methods and fields.
* Combinator methods, which combine or transform pre-existing method handles into new ones.
* Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
- * Wrapper methods which can convert between method handles and other function-like "SAM types".
+ * Wrapper methods which can convert between method handles and interface types.
*
*
* @author John Rose, JSR 292 EG
@@ -58,15 +52,14 @@ public class MethodHandles {
private MethodHandles() { } // do not instantiate
- private static final Access IMPL_TOKEN = Access.getToken();
- private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
+ private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
static { MethodHandleImpl.initStatics(); }
// See IMPL_LOOKUP below.
//// Method handle creation from ordinary methods.
/**
- * Return a {@link Lookup lookup object} on the caller,
+ * Returns a {@link Lookup lookup object} on the caller,
* which has the capability to access any method handle that the caller has access to,
* including direct method handles to private fields and methods.
* This lookup object is a capability which may be delegated to trusted agents.
@@ -77,7 +70,7 @@ public class MethodHandles {
}
/**
- * Return a {@link Lookup lookup object} which is trusted minimally.
+ * Returns a {@link Lookup lookup object} which is trusted minimally.
* It can only be used to create method handles to
* publicly accessible fields and methods.
*
@@ -120,55 +113,55 @@ public class MethodHandles {
*
* lookup expression member behavior
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}
* FT f; (T) this.f;
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}
* static FT f; (T) C.f;
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}
* FT f; this.f = x;
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}
* static FT f; C.f = arg;
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}
* T m(A*); (T) this.m(arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}
* static T m(A*); (T) C.m(arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}
* T m(A*); (T) super.m(arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}
* C(A*); (T) new C(arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}
* (static)? FT f; (FT) aField.get(thisOrNull);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}
* (static)? FT f; aField.set(thisOrNull, arg);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}
* (static)? T m(A*); (T) aMethod.invoke(thisOrNull, arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}
* C(A*); (C) aConstructor.newInstance(arg*);
*
*
- * {@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}
* (static)? T m(A*); (T) aMethod.invoke(thisOrNull, arg*);
*
*
@@ -383,10 +376,10 @@ public class MethodHandles {
* and {@linkplain #PACKAGE PACKAGE (0x08)}.
*
* A freshly-created lookup object
- * on the {@linkplain java.dyn.MethodHandles#lookup() caller's class}
+ * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
* has all possible bits set, since the caller class can access all its own members.
* A lookup object on a new lookup class
- * {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
* The purpose of this is to restrict access via the new lookup object,
* so that it can access only names which can be reached by the original
@@ -410,9 +403,8 @@ public class MethodHandles {
checkUnprivilegedlookupClass(lookupClass);
}
- Lookup(Access token, Class> lookupClass) {
+ Lookup(Class> lookupClass) {
this(lookupClass, ALL_MODES);
- Access.check(token);
}
private Lookup(Class> lookupClass, int allowedModes) {
@@ -471,7 +463,7 @@ public class MethodHandles {
}
// Make sure outer class is initialized first.
- static { IMPL_TOKEN.getClass(); }
+ static { IMPL_NAMES.getClass(); }
/** Version of lookup which is trusted minimally.
* It can only be used to create method handles to
@@ -481,11 +473,10 @@ public class MethodHandles {
/** Package-private version of lookup which is trusted. */
static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
- static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
private static void checkUnprivilegedlookupClass(Class> lookupClass) {
String name = lookupClass.getName();
- if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
+ if (name.startsWith("java.lang.invoke."))
throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
}
@@ -506,8 +497,8 @@ public class MethodHandles {
* access (public, package, private, and protected) is allowed.
* In this case, no suffix is added.
* This is true only of an object obtained originally from
- * {@link java.dyn.MethodHandles#lookup MethodHandles.lookup}.
- * Objects created by {@link java.dyn.MethodHandles.Lookup#in Lookup.in}
+ * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+ * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
* always have restricted access, and will display a suffix.
*
* (It may seem strange that protected access should be
@@ -577,7 +568,7 @@ public class MethodHandles {
MethodHandle findStatic(Class> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, true);
checkMethod(refc, method, true);
- return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
+ return MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
}
/**
@@ -601,8 +592,8 @@ public class MethodHandles {
* if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invokeGeneric}, the resulting
* method handle is equivalent to one produced by
- * {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
- * {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}
+ * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
+ * {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}
* with the same {@code type} argument.
*
* @param refc the class or interface from which the method is accessed
@@ -618,7 +609,7 @@ public class MethodHandles {
public MethodHandle findVirtual(Class> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, false);
checkMethod(refc, method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
+ MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
return restrictProtectedReceiver(method, mh);
}
@@ -651,8 +642,8 @@ public class MethodHandles {
MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
assert(ctor.isConstructor());
checkAccess(refc, ctor);
- MethodHandle rawMH = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
- MethodHandle allocMH = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawMH);
+ MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+ MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH);
return fixVarargs(allocMH, rawMH);
}
@@ -708,7 +699,7 @@ public class MethodHandles {
checkSpecialCaller(specialCaller);
MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
checkMethod(refc, method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller);
+ MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller);
return restrictReceiver(method, mh, specialCaller);
}
@@ -839,17 +830,17 @@ return mh1;
Class extends Object> refc = receiver.getClass(); // may get NPE
MemberName method = resolveOrFail(refc, name, type, false);
checkMethod(refc, method, false);
- MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
- MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
+ MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver);
if (bmh == null)
- throw newNoAccessException(method, this);
+ throw method.makeAccessException("no access", this);
if (dmh.type().parameterCount() == 0)
return dmh; // bound the trailing parameter; no varargs possible
return fixVarargs(bmh, dmh);
}
/**
- * Make a direct method handle to m , if the lookup class has permission.
+ * Makes a direct method handle to m , if the lookup class has permission.
* If m is non-static, the receiver argument is treated as an initial argument.
* If m is virtual, overriding is respected on every call.
* Unlike the Core Reflection API, exceptions are not wrapped.
@@ -871,7 +862,7 @@ return mh1;
MemberName method = new MemberName(m);
assert(method.isMethod());
if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic());
- MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClassOrNull());
+ MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh);
return mh;
}
@@ -901,7 +892,7 @@ return mh1;
assert(method.isMethod());
// ignore m.isAccessible: this is a new kind of access
checkMethod(m.getDeclaringClass(), method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClassOrNull());
+ MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
return restrictReceiver(method, mh, specialCaller);
}
@@ -928,8 +919,8 @@ return mh1;
MemberName ctor = new MemberName(c);
assert(ctor.isConstructor());
if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor);
- MethodHandle rawCtor = MethodHandleImpl.findMethod(IMPL_TOKEN, ctor, false, lookupClassOrNull());
- MethodHandle allocator = MethodHandleImpl.makeAllocator(IMPL_TOKEN, rawCtor);
+ MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+ MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor);
return fixVarargs(allocator, rawCtor);
}
@@ -940,7 +931,7 @@ return mh1;
* If the field is static, the method handle will take no arguments.
* Otherwise, its single argument will be the instance containing
* the field.
- * If the method's {@code accessible} flag is not set,
+ * If the field's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field
* @return a method handle which can load values from the reflected field
@@ -958,7 +949,7 @@ return mh1;
* argument, of the field's value type, the value to be stored.
* Otherwise, the two arguments will be the instance containing
* the field, and the value to be stored.
- * If the method's {@code accessible} flag is not set,
+ * If the field's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field
* @return a method handle which can store values into the reflected field
@@ -999,7 +990,7 @@ return mh1;
void checkSymbolicClass(Class> refc) throws IllegalAccessException {
Class> caller = lookupClassOrNull();
if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
- throw newNoAccessException("symbolic reference class is not public", new MemberName(refc), this);
+ throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
}
void checkMethod(Class> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
@@ -1012,7 +1003,7 @@ return mh1;
message = wantStatic ? "expected a static method" : "expected a non-static method";
else
{ checkAccess(refc, m); return; }
- throw newNoAccessException(message, m, this);
+ throw m.makeAccessException(message, this);
}
void checkAccess(Class> refc, MemberName m) throws IllegalAccessException {
@@ -1030,7 +1021,7 @@ return mh1;
&& VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
// Protected members can also be checked as if they were package-private.
return;
- throw newNoAccessException(accessFailedMessage(refc, m), m, this);
+ throw m.makeAccessException(accessFailedMessage(refc, m), this);
}
String accessFailedMessage(Class> refc, MemberName m) {
@@ -1064,8 +1055,8 @@ return mh1;
|| (specialCaller != lookupClass()
&& !(ALLOW_NESTMATE_ACCESS &&
VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
- throw newNoAccessException("no private access for invokespecial",
- new MemberName(specialCaller), this);
+ throw new MemberName(specialCaller).
+ makeAccessException("no private access for invokespecial", this);
}
MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
@@ -1084,12 +1075,12 @@ return mh1;
assert(!method.isStatic());
Class> defc = method.getDeclaringClass(); // receiver type of mh is too wide
if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
- throw newNoAccessException("caller class must be a subclass below the method", method, caller);
+ throw method.makeAccessException("caller class must be a subclass below the method", caller);
}
MethodType rawType = mh.type();
if (rawType.parameterType(0) == caller) return mh;
MethodType narrowType = rawType.changeParameterType(0, caller);
- MethodHandle narrowMH = MethodHandleImpl.convertArguments(IMPL_TOKEN, mh, narrowType, rawType, null);
+ MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, null);
return fixVarargs(narrowMH, mh);
}
@@ -1097,10 +1088,9 @@ return mh1;
boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(refc, name, type, isStatic);
if (isStatic != field.isStatic())
- throw newNoAccessException(isStatic
- ? "expected a static field"
- : "expected a non-static field",
- field, this);
+ throw field.makeAccessException(isStatic
+ ? "expected a static field"
+ : "expected a non-static field", this);
return makeAccessor(refc, field, false, isSetter);
}
@@ -1108,9 +1098,9 @@ return mh1;
boolean trusted, boolean isSetter) throws IllegalAccessException {
assert(field.isField());
if (trusted)
- return MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
+ return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
checkAccess(refc, field);
- MethodHandle mh = MethodHandleImpl.accessField(IMPL_TOKEN, field, isSetter, lookupClassOrNull());
+ MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
return restrictProtectedReceiver(field, mh);
}
}
@@ -1127,7 +1117,7 @@ return mh1;
*/
public static
MethodHandle arrayElementGetter(Class> arrayClass) throws IllegalArgumentException {
- return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, false);
+ return MethodHandleImpl.accessArrayElement(arrayClass, false);
}
/**
@@ -1141,7 +1131,7 @@ return mh1;
*/
public static
MethodHandle arrayElementSetter(Class> arrayClass) throws IllegalArgumentException {
- return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
+ return MethodHandleImpl.accessArrayElement(arrayClass, true);
}
/// method handle invocation (reflective style)
@@ -1191,7 +1181,7 @@ return invoker;
MethodHandle spreadInvoker(MethodType type, int objectArgCount) {
if (objectArgCount < 0 || objectArgCount > type.parameterCount())
throw new IllegalArgumentException("bad argument count "+objectArgCount);
- return invokers(type).spreadInvoker(objectArgCount);
+ return type.invokers().spreadInvoker(objectArgCount);
}
/**
@@ -1231,7 +1221,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
*/
static public
MethodHandle exactInvoker(MethodType type) {
- return invokers(type).exactInvoker();
+ return type.invokers().exactInvoker();
}
/**
@@ -1258,11 +1248,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
*/
static public
MethodHandle genericInvoker(MethodType type) {
- return invokers(type).genericInvoker();
- }
-
- static Invokers invokers(MethodType type) {
- return MethodTypeImpl.invokers(IMPL_TOKEN, type);
+ return type.invokers().genericInvoker();
}
/**
@@ -1387,7 +1373,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
return target;
MethodHandle res = null;
try {
- res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
+ res = MethodHandleImpl.convertArguments(target,
newType, oldType, null);
} catch (IllegalArgumentException ex) {
}
@@ -1531,7 +1517,7 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
MethodType oldType = target.type();
checkReorder(reorder, newType, oldType);
- return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
+ return MethodHandleImpl.convertArguments(target,
newType, oldType,
reorder);
}
@@ -1574,7 +1560,7 @@ assert((int)twice.invokeExact(21) == 42);
int numSpread = (outargs - spreadPos);
MethodHandle res = null;
if (spreadPos >= 0 && numSpread >= 0) {
- res = MethodHandleImpl.spreadArguments(IMPL_TOKEN, target, newType, spreadPos);
+ res = MethodHandleImpl.spreadArguments(target, newType, spreadPos);
}
if (res == null) {
throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
@@ -1607,7 +1593,7 @@ assert((int)twice.invokeExact(21) == 42);
int numCollect = (inargs - collectPos);
if (collectPos < 0 || numCollect < 0)
throw newIllegalArgumentException("wrong number of arguments");
- MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
+ MethodHandle res = MethodHandleImpl.collectArguments(target, newType, collectPos, null);
if (res == null) {
throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
}
@@ -1654,7 +1640,13 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle identity(Class> type) {
if (type == void.class)
throw newIllegalArgumentException("void type");
- return ValueConversions.identity(type);
+ else if (type == Object.class)
+ return ValueConversions.identity();
+ else if (type.isPrimitive())
+ return ValueConversions.identity(Wrapper.forPrimitiveType(type));
+ else
+ return AdapterMethodHandle.makeRetypeRaw(
+ MethodType.methodType(type, type), ValueConversions.identity());
}
/**
@@ -1686,8 +1678,6 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
int insCount = values.length;
MethodType oldType = target.type();
- ArrayList> ptypes =
- new ArrayList>(oldType.parameterList());
int outargs = oldType.parameterCount();
int inargs = outargs - insCount;
if (inargs < 0)
@@ -1701,14 +1691,14 @@ assert((int)twice.invokeExact(21) == 42);
value = checkValue(valueType, value);
if (pos == 0 && !valueType.isPrimitive()) {
// At least for now, make bound method handles a special case.
- MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(result, value);
if (bmh != null) {
result = bmh;
continue;
}
// else fall through to general adapter machinery
}
- result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
+ result = MethodHandleImpl.bindArgument(result, pos, value);
}
return result;
}
@@ -1726,20 +1716,21 @@ assert((int)twice.invokeExact(21) == 42);
*
* Example:
*
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle d0 = dropArguments(cat, 0, String.class);
-assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
-MethodHandle d1 = dropArguments(cat, 1, String.class);
-assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
-MethodHandle d2 = dropArguments(cat, 2, String.class);
-assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
-MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
-assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+ *
+ *
+ * This method is also equivalent to the following code:
+ *
+ * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0]))
*
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
@@ -1762,7 +1753,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
new ArrayList>(oldType.parameterList());
ptypes.addAll(pos, valueTypes);
MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
- return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
+ return MethodHandleImpl.dropArguments(target, newType, pos);
}
/**
@@ -1770,10 +1761,34 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* after dropping the given argument(s) at the given position.
* The type of the new method handle will insert the given argument
* type(s), at that position, into the original handle's type.
- * This method is equivalent to the following code:
- *
+ *
+ * The pos may range between zero and N ,
+ * where N is the number of argument types in target ,
+ * meaning to drop the first or last argument (respectively),
+ * or an argument somewhere in between.
+ *
+ * Example:
+ *
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+ *
+ *
+ * This method is also equivalent to the following code:
+ *
* {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
- *
+ *
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
* @param pos position of first argument to drop (zero for the leftmost)
@@ -1789,7 +1804,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
}
/**
- * Adapt a target method handle {@code target} by pre-processing
+ * Adapts a target method handle {@code target} by pre-processing
* one or more of its arguments, each with its own unary filter function,
* and then calling the target with each pre-processed argument
* replaced by the result of its corresponding filter function.
@@ -1812,8 +1827,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* which do not correspond to argument positions in the target.
* Example:
*
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
@@ -1855,16 +1870,16 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
|| filterType.returnType() != targetType.parameterType(curPos))
throw newIllegalArgumentException("target and filter types do not match");
adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
- adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter);
+ adapter = MethodHandleImpl.filterArgument(adapter, curPos, filter);
}
MethodType midType = adapter.type();
if (midType != adapterType)
- adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
+ adapter = MethodHandleImpl.convertArguments(adapter, adapterType, midType, null);
return adapter;
}
/**
- * Adapt a target method handle {@code target} by post-processing
+ * Adapts a target method handle {@code target} by post-processing
* its return value with a unary filter function.
*
* If a filter {@code F} applies to the return value of
@@ -1876,8 +1891,8 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* return type of the target.
* Example:
*
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
@@ -1909,7 +1924,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
/**
- * Adapt a target method handle {@code target} by pre-processing
+ * Adapts a target method handle {@code target} by pre-processing
* some of its arguments, and then calling the target with
* the result of the pre-processing, plus all original arguments.
*
@@ -1966,11 +1981,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
if (!ok)
throw misMatchedTypes("target and combiner types", targetType, combinerType);
MethodType newType = targetType.dropParameterTypes(0, 1);
- return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
+ return MethodHandleImpl.foldArguments(target, newType, combiner);
}
/**
- * Make a method handle which adapts a target method handle,
+ * Makes a method handle which adapts a target method handle,
* by guarding it with a test, a boolean-valued method handle.
* If the guard fails, a fallback handle is called instead.
* All three method handles must have the same corresponding
@@ -2021,7 +2036,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
test = dropArguments(test, gpc, targs.subList(gpc, tpc));
gtype = test.type();
}
- return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
+ return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
}
static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
@@ -2029,7 +2044,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
/**
- * Make a method handle which adapts a target method handle,
+ * Makes a method handle which adapts a target method handle,
* by running it inside an exception handler.
* If the target returns normally, the adapter returns that value.
* If an exception matching the specified type is thrown, the fallback
@@ -2092,7 +2107,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
htype = handler.type();
}
- return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
+ return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
}
/**
@@ -2107,51 +2122,45 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
*/
public static
MethodHandle throwException(Class> returnType, Class extends Throwable> exType) {
- return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
+ return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
}
/**
- * Produces an instance of the given "SAM" interface which redirects
+ * Produces an instance of the given single-method interface which redirects
* its calls to the given method handle.
*
- * A SAM interface is an interface which declares a single abstract method.
- * When determining the unique abstract method of a SAM interface,
+ * A single-method interface is an interface which declares a unique method.
+ * When determining the unique method of a single-method interface,
* the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
- * are disregarded. For example, {@link java.util.Comparator} is a SAM interface,
+ * are disregarded. For example, {@link java.util.Comparator} is a single-method interface,
* even though it re-declares the {@code Object.equals} method.
- * Also, if the SAM interface has a supertype,
- * the SAM interface may override an inherited method.
- * Any such overrides are respected, and the method handle will be accessible
- * by either the inherited method or the SAM method.
- * In particular, a {@linkplain java.lang.reflect.Method#isBridge bridge method}
- * may be created if the methods have different return types.
*
* The type must be public. No additional access checks are performed.
*
- * The resulting instance of the required SAM type will respond to
- * invocation of the SAM type's single abstract method by calling
+ * The resulting instance of the required type will respond to
+ * invocation of the type's single abstract method by calling
* the given {@code target} on the incoming arguments,
* and returning or throwing whatever the {@code target}
* returns or throws. The invocation will be as if by
* {@code target.invokeGeneric}.
- * The target's type will be checked before the SAM
+ * The target's type will be checked before the
* instance is created, as if by a call to {@code asType},
* which may result in a {@code WrongMethodTypeException}.
*
- * The wrapper instance will implement the requested SAM interface
- * and its super-types, but no other SAM types.
- * This means that the SAM instance will not unexpectedly
+ * The wrapper instance will implement the requested interface
+ * and its super-types, but no other single-method interfaces.
+ * This means that the instance will not unexpectedly
* pass an {@code instanceof} test for any unrequested type.
*
* Implementation Note:
- * Therefore, each SAM instance must implement a unique SAM type.
+ * Therefore, each instance must implement a unique single-method interface.
* Implementations may not bundle together
- * multiple SAM types onto single implementation classes
+ * multiple single-method interfaces onto single implementation classes
* in the style of {@link java.awt.AWTEventMulticaster}.
*
* The method handle may throw an undeclared exception ,
* which means any checked exception (or other checked throwable)
- * not declared by the SAM type's single abstract method.
+ * not declared by the requested type's single abstract method.
* If this happens, the throwable will be wrapped in an instance of
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
* and thrown in that wrapped form.
@@ -2161,28 +2170,37 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* by their behavior.
* It is not guaranteed to return a new instance for every call.
*
+ * Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
+ * and other corner cases, the interface may also have several abstract methods
+ * with the same name but having distinct descriptors (types of returns and parameters).
+ * In this case, all the methods are bound in common to the one given {@code target}.
+ * The type check and effective {@code asType} conversion is applied to each
+ * method type descriptor, and all abstract methods are bound to the {@code target} in common.
+ * Beyond this type check, no further checks are made to determine that the
+ * abstract methods are related in any way.
+ *
* Future versions of this API may accept additional types,
* such as abstract classes with single abstract methods.
* Future versions of this API may also equip wrapper instances
* with one or more additional public "marker" interfaces.
*
* @param target the method handle to invoke from the wrapper
- * @param samType the desired type of the wrapper, a SAM type
+ * @param smType the desired type of the wrapper, a single-method interface
* @return a correctly-typed wrapper for the given {@code target}
* @throws NullPointerException if either argument is null
- * @throws IllegalArgumentException if the {@code samType} is not a
+ * @throws IllegalArgumentException if the {@code smType} is not a
* valid argument to this method
* @throws WrongMethodTypeException if the {@code target} cannot
- * be converted to the type required by the SAM type
+ * be converted to the type required by the requested interface
*/
// Other notes to implementors:
//
- // No stable mapping is promised between the SAM type and
+ // No stable mapping is promised between the single-method interface and
// the implementation class C. Over time, several implementation
- // classes might be used for the same SAM type.
+ // classes might be used for the same type.
//
// If the implementation is able
- // to prove that a wrapper of the required SAM type
+ // to prove that a wrapper of the required type
// has already been created for a given
// method handle, or for another method handle with the
// same behavior, the implementation may return that wrapper in place of
@@ -2191,34 +2209,34 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
// This method is designed to apply to common use cases
// where a single method handle must interoperate with
// an interface that implements a function-like
- // API. Additional variations, such as SAM classes with
+ // API. Additional variations, such as single-abstract-method classes with
// private constructors, or interfaces with multiple but related
// entry points, must be covered by hand-written or automatically
// generated adapter classes.
//
public static
- T asInstance(final MethodHandle target, final Class samType) {
+ T asInstance(final MethodHandle target, final Class smType) {
// POC implementation only; violates the above contract several ways
- final Method sam = getSamMethod(samType);
- if (sam == null)
- throw new IllegalArgumentException("not a SAM type: "+samType.getName());
- MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
- MethodHandle checkTarget = target.asType(samMT); // make throw WMT
+ final Method sm = getSingleMethod(smType);
+ if (sm == null)
+ throw new IllegalArgumentException("not a single-method interface: "+smType.getName());
+ MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
+ MethodHandle checkTarget = target.asType(smMT); // make throw WMT
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
- final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, samMT.parameterCount());
- return samType.cast(Proxy.newProxyInstance(
- samType.getClassLoader(),
- new Class[]{ samType, WrapperInstance.class },
+ final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
+ return smType.cast(Proxy.newProxyInstance(
+ smType.getClassLoader(),
+ new Class[]{ smType, WrapperInstance.class },
new InvocationHandler() {
private Object getArg(String name) {
if ((Object)name == "getWrapperInstanceTarget") return target;
- if ((Object)name == "getWrapperInstanceType") return samType;
+ if ((Object)name == "getWrapperInstanceType") return smType;
throw new AssertionError();
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == WrapperInstance.class)
return getArg(method.getName());
- if (method.equals(sam))
+ if (method.equals(sm))
return vaTarget.invokeExact(args);
if (isObjectMethod(method))
return callObjectMethod(this, method, args);
@@ -2228,7 +2246,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
/**
- * Determine if the given object was produced by a call to {@link #asInstance asInstance}.
+ * Determines if the given object was produced by a call to {@link #asInstance asInstance}.
* @param x any reference
* @return true if the reference is not null and points to an object produced by {@code asInstance}
*/
@@ -2248,11 +2266,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
/**
* Produces or recovers a target method handle which is behaviorally
- * equivalent to the SAM method of this wrapper instance.
+ * equivalent to the unique method of this wrapper instance.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
- * @return a method handle implementing the SAM method
+ * @return a method handle implementing the unique method
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
public static
@@ -2261,11 +2279,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
/**
- * Recover the SAM type for which this wrapper instance was created.
+ * Recovers the unique single-method interface type for which this wrapper instance was created.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
- * @return the SAM type for which the wrapper was created
+ * @return the single-method interface type for which the wrapper was created
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
public static
@@ -2305,24 +2323,24 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
private static
- Method getSamMethod(Class> samType) {
- Method sam = null;
- for (Method m : samType.getMethods()) {
+ Method getSingleMethod(Class> smType) {
+ Method sm = null;
+ for (Method m : smType.getMethods()) {
int mod = m.getModifiers();
if (Modifier.isAbstract(mod)) {
- if (sam != null && !isObjectMethod(sam))
+ if (sm != null && !isObjectMethod(sm))
return null; // too many abstract methods
- sam = m;
+ sm = m;
}
}
- if (!samType.isInterface() && getSamConstructor(samType) == null)
+ if (!smType.isInterface() && getSingleConstructor(smType) == null)
return null; // wrong kind of constructor
- return sam;
+ return sm;
}
private static
- Constructor getSamConstructor(Class> samType) {
- for (Constructor c : samType.getDeclaredConstructors()) {
+ Constructor getSingleConstructor(Class> smType) {
+ for (Constructor c : smType.getDeclaredConstructors()) {
if (c.getParameterTypes().length == 0) {
int mod = c.getModifiers();
if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
@@ -2334,6 +2352,6 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
/*non-public*/
static MethodHandle asVarargsCollector(MethodHandle target, Class> arrayType) {
- return MethodHandleImpl.asVarargsCollector(IMPL_TOKEN, target, arrayType);
+ return MethodHandleImpl.asVarargsCollector(target, arrayType);
}
}
diff --git a/jdk/src/share/classes/java/dyn/MethodType.java b/jdk/src/share/classes/java/lang/invoke/MethodType.java
similarity index 93%
rename from jdk/src/share/classes/java/dyn/MethodType.java
rename to jdk/src/share/classes/java/lang/invoke/MethodType.java
index a7baf7c634e..a7fa147fa32 100644
--- a/jdk/src/share/classes/java/dyn/MethodType.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java
@@ -23,18 +23,14 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import sun.dyn.Access;
-import sun.dyn.Invokers;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.MethodTypeImpl;
-import sun.dyn.util.BytecodeDescriptor;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import sun.invoke.util.BytecodeDescriptor;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* A method type represents the arguments and return type accepted and
@@ -96,34 +92,6 @@ class MethodType implements java.io.Serializable {
private MethodType wrapAlt; // alternative wrapped/unwrapped version
private Invokers invokers; // cache of handy higher-order adapters
- private static final Access IMPL_TOKEN = Access.getToken();
-
- // share a cache with a friend in this package
- Invokers getInvokers() { return invokers; }
- void setInvokers(Invokers inv) { invokers = inv; }
-
- static {
- // This hack allows the implementation package special access to
- // the internals of MethodType. In particular, the MTImpl has all sorts
- // of cached information useful to the implementation code.
- MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
- public Class>[] ptypes(MethodType mt) { return mt.ptypes; }
- public MethodTypeImpl form(MethodType mt) { return mt.form; }
- public void setForm(MethodType mt, MethodTypeImpl form) {
- assert(mt.form == null);
- mt.form = (MethodTypeForm) form;
- }
- public MethodType makeImpl(Class> rtype, Class>[] ptypes, boolean trusted) {
- return MethodType.makeImpl(rtype, ptypes, trusted);
- }
- public MethodTypeImpl newMethodTypeForm(MethodType mt) {
- return new MethodTypeForm(mt);
- }
- public Invokers getInvokers(MethodType mt) { return mt.invokers; }
- public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; }
- });
- }
-
/**
* Check the given parameters for validity and store them into the final fields.
*/
@@ -134,6 +102,10 @@ class MethodType implements java.io.Serializable {
this.ptypes = ptypes;
}
+ /*trusted*/ MethodTypeForm form() { return form; }
+ /*trusted*/ Class> rtype() { return rtype; }
+ /*trusted*/ Class>[] ptypes() { return ptypes; }
+
private static void checkRtype(Class> rtype) {
rtype.equals(rtype); // null check
}
@@ -168,7 +140,7 @@ class MethodType implements java.io.Serializable {
static final Class>[] NO_PTYPES = {};
/**
- * Find or create an instance of the given method type.
+ * Finds or creates an instance of the given method type.
* @param rtype the return type
* @param ptypes the parameter types
* @return a method type with the given components
@@ -253,7 +225,7 @@ class MethodType implements java.io.Serializable {
* @param trusted whether the ptypes can be used without cloning
* @return the unique method type of the desired structure
*/
- private static
+ /*trusted*/ static
MethodType makeImpl(Class> rtype, Class>[] ptypes, boolean trusted) {
if (ptypes == null || ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true;
@@ -269,7 +241,12 @@ class MethodType implements java.io.Serializable {
// defensively copy the array passed in by the user
mt1 = new MethodType(rtype, ptypes.clone());
// promote the object to the Real Thing, and reprobe
- MethodTypeImpl.initForm(IMPL_TOKEN, mt1);
+ MethodTypeForm form = MethodTypeForm.findForm(mt1);
+ mt1.form = form;
+ if (form.erasedType == mt1) {
+ // This is a principal (erased) type; show it to the JVM.
+ MethodHandleNatives.init(mt1);
+ }
synchronized (internTable) {
mt0 = internTable.get(mt1);
if (mt0 != null)
@@ -279,12 +256,6 @@ class MethodType implements java.io.Serializable {
return mt1;
}
- // Entry point from JVM. TODO: Change the name & signature.
- private static MethodType makeImpl(Class> rtype, Class>[] ptypes,
- boolean ignore1, boolean ignore2) {
- return makeImpl(rtype, ptypes, true);
- }
-
private static final MethodType[] objectOnlyTypes = new MethodType[20];
/**
@@ -519,7 +490,7 @@ class MethodType implements java.io.Serializable {
}
/**
- * Convert all wrapper types to their corresponding primitive types.
+ * Converts all wrapper types to their corresponding primitive types.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* All primitive types (including {@code void}) will remain unchanged.
* A return type of {@code java.lang.Void} is changed to {@code void}.
@@ -535,7 +506,7 @@ class MethodType implements java.io.Serializable {
MethodType wt = pt.wrapAlt;
if (wt == null) {
// fill in lazily
- wt = MethodTypeImpl.canonicalize(pt, MethodTypeImpl.WRAP, MethodTypeImpl.WRAP);
+ wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
assert(wt != null);
pt.wrapAlt = wt;
}
@@ -547,7 +518,7 @@ class MethodType implements java.io.Serializable {
MethodType uwt = wt.wrapAlt;
if (uwt == null) {
// fill in lazily
- uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP);
+ uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
if (uwt == null)
uwt = wt; // type has no wrappers or prims at all
wt.wrapAlt = uwt;
@@ -658,7 +629,7 @@ class MethodType implements java.io.Serializable {
/// Queries which have to do with the bytecode architecture
/** Reports the number of JVM stack slots required to invoke a method
- * of this type. Note that (for historic reasons) the JVM requires
+ * of this type. Note that (for historical reasons) the JVM requires
* a second stack slot to pass long and double arguments.
* So this method returns {@link #parameterCount() parameterCount} plus the
* number of long and double parameters (if any).
@@ -666,12 +637,18 @@ class MethodType implements java.io.Serializable {
* This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* @return the number of JVM stack slots for this type's parameters
- * @deprecated Will be removed for PFD.
*/
- public int parameterSlotCount() {
+ /*non-public*/ int parameterSlotCount() {
return form.parameterSlotCount();
}
+ /*non-public*/ Invokers invokers() {
+ Invokers inv = invokers;
+ if (inv != null) return inv;
+ invokers = inv = new Invokers(this);
+ return inv;
+ }
+
/** Reports the number of JVM stack slots which carry all parameters including and after
* the given position, which must be in the range of 0 to
* {@code parameterCount} inclusive. Successive parameters are
@@ -694,9 +671,8 @@ class MethodType implements java.io.Serializable {
* @return the index of the (shallowest) JVM stack slot transmitting the
* given parameter
* @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
- * @deprecated Will be removed for PFD.
*/
- public int parameterSlotDepth(int num) {
+ /*non-public*/ int parameterSlotDepth(int num) {
if (num < 0 || num > ptypes.length)
parameterType(num); // force a range check
return form.parameterToArgSlot(num-1);
@@ -710,14 +686,14 @@ class MethodType implements java.io.Serializable {
* This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* @return the number of JVM stack slots (0, 1, or 2) for this type's return value
- * @deprecated Will be removed for PFD.
+ * Will be removed for PFD.
*/
- public int returnSlotCount() {
+ /*non-public*/ int returnSlotCount() {
return form.returnSlotCount();
}
/**
- * Find or create an instance of a method type, given the spelling of its bytecode descriptor.
+ * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* Any class or interface name embedded in the descriptor string
* will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
diff --git a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
similarity index 85%
rename from jdk/src/share/classes/sun/dyn/MethodTypeImpl.java
rename to jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
index 700ed307f74..db73b24d067 100644
--- a/jdk/src/share/classes/sun/dyn/MethodTypeImpl.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
@@ -23,11 +23,10 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
-import sun.dyn.util.Wrapper;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
/**
* Shared information for a group of method types, which differ
@@ -42,7 +41,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* No more than half of these are likely to be loaded at once.
* @author John Rose
*/
-public class MethodTypeImpl {
+class MethodTypeForm {
final int[] argToSlotTable, slotToArgTable;
final long argCounts; // packed slot & value counts
final long primCounts; // packed prim & double counts
@@ -66,39 +65,10 @@ public class MethodTypeImpl {
return erasedType;
}
- public static MethodTypeImpl of(MethodType type) {
- return METHOD_TYPE_FRIEND.form(type);
- }
-
- /** Access methods for the internals of MethodType, supplied to
- * MethodTypeImpl as a trusted agent.
- */
- static public interface MethodTypeFriend {
- Class>[] ptypes(MethodType mt);
- MethodTypeImpl form(MethodType mt);
- void setForm(MethodType mt, MethodTypeImpl form);
- MethodType makeImpl(Class> rtype, Class>[] ptypes, boolean trusted);
- MethodTypeImpl newMethodTypeForm(MethodType mt);
- Invokers getInvokers(MethodType mt);
- void setInvokers(MethodType mt, Invokers inv);
- }
- public static void setMethodTypeFriend(Access token, MethodTypeFriend am) {
- Access.check(token);
- if (METHOD_TYPE_FRIEND != null)
- throw new InternalError(); // just once
- METHOD_TYPE_FRIEND = am;
- }
- static private MethodTypeFriend METHOD_TYPE_FRIEND;
-
- static MethodType makeImpl(Access token, Class> rtype, Class>[] ptypes, boolean trusted) {
- Access.check(token);
- return METHOD_TYPE_FRIEND.makeImpl(rtype, ptypes, trusted);
- }
-
- protected MethodTypeImpl(MethodType erasedType) {
+ protected MethodTypeForm(MethodType erasedType) {
this.erasedType = erasedType;
- Class>[] ptypes = METHOD_TYPE_FRIEND.ptypes(erasedType);
+ Class>[] ptypes = erasedType.ptypes();
int ptypeCount = ptypes.length;
int pslotCount = ptypeCount; // temp. estimate
int rtypeCount = 1; // temp. estimate
@@ -260,7 +230,7 @@ public class MethodTypeImpl {
* the type {@code (Object,int)Object} produces {@code null}.
*/
public static int[] primsAtEndOrder(MethodType mt) {
- MethodTypeImpl form = METHOD_TYPE_FRIEND.form(mt);
+ MethodTypeForm form = mt.form();
if (form.primsAtEnd == form.erasedType)
// quick check shows no reordering is necessary
return null;
@@ -273,7 +243,7 @@ public class MethodTypeImpl {
int lac = form.longPrimitiveParameterCount();
int rfill = 0, ifill = argc - pac, lfill = argc - lac;
- Class>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
+ Class>[] ptypes = mt.ptypes();
boolean changed = false;
for (int i = 0; i < ptypes.length; i++) {
Class> pt = ptypes[i];
@@ -300,7 +270,7 @@ public class MethodTypeImpl {
*/
public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class>[] moreParams) {
if (newParamOrder == null) return mt; // no-op reordering
- Class>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
+ Class>[] ptypes = mt.ptypes();
Class>[] ntypes = new Class>[newParamOrder.length];
int maxParam = ptypes.length + (moreParams == null ? 0 : moreParams.length);
boolean changed = (ntypes.length != ptypes.length);
@@ -314,7 +284,7 @@ public class MethodTypeImpl {
ntypes[i] = nt;
}
if (!changed) return mt;
- return METHOD_TYPE_FRIEND.makeImpl(mt.returnType(), ntypes, true);
+ return MethodType.makeImpl(mt.returnType(), ntypes, true);
}
private static boolean hasTwoArgSlots(Class> type) {
@@ -376,28 +346,18 @@ public class MethodTypeImpl {
return slotToArgTable[argSlot] - 1;
}
- public static void initForm(Access token, MethodType mt) {
- Access.check(token);
- MethodTypeImpl form = findForm(mt);
- METHOD_TYPE_FRIEND.setForm(mt, form);
- if (form.erasedType == mt) {
- // This is a principal (erased) type; show it to the JVM.
- MethodHandleImpl.init(token, mt);
- }
- }
-
- static MethodTypeImpl findForm(MethodType mt) {
+ static MethodTypeForm findForm(MethodType mt) {
MethodType erased = canonicalize(mt, ERASE, ERASE);
if (erased == null) {
- // It is already erased. Make a new MethodTypeImpl.
- return METHOD_TYPE_FRIEND.newMethodTypeForm(mt);
+ // It is already erased. Make a new MethodTypeForm.
+ return new MethodTypeForm(mt);
} else {
- // Share the MethodTypeImpl with the erased version.
- return METHOD_TYPE_FRIEND.form(erased);
+ // Share the MethodTypeForm with the erased version.
+ return erased.form();
}
}
- /** Codes for {@link #canonicalize(java.lang.Class, int).
+ /** Codes for {@link #canonicalize(java.lang.Class, int)}.
* ERASE means change every reference to {@code Object}.
* WRAP means convert primitives (including {@code void} to their
* corresponding wrapper types. UNWRAP means the reverse of WRAP.
@@ -414,10 +374,10 @@ public class MethodTypeImpl {
* Otherwise return null.
*/
public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
- Class>[] ptypes = METHOD_TYPE_FRIEND.ptypes(mt);
- Class>[] ptc = MethodTypeImpl.canonicalizes(ptypes, howArgs);
+ Class>[] ptypes = mt.ptypes();
+ Class>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
Class> rtype = mt.returnType();
- Class> rtc = MethodTypeImpl.canonicalize(rtype, howRet);
+ Class> rtc = MethodTypeForm.canonicalize(rtype, howRet);
if (ptc == null && rtc == null) {
// It is already canonical.
return null;
@@ -425,7 +385,7 @@ public class MethodTypeImpl {
// Find the erased version of the method type:
if (rtc == null) rtc = rtype;
if (ptc == null) ptc = ptypes;
- return METHOD_TYPE_FRIEND.makeImpl(rtc, ptc, true);
+ return MethodType.makeImpl(rtc, ptc, true);
}
/** Canonicalize the given return or param type.
@@ -496,16 +456,16 @@ public class MethodTypeImpl {
return cs;
}
- public static Invokers invokers(Access token, MethodType type) {
- Access.check(token);
- return invokers(type);
- }
- /*non-public*/ static Invokers invokers(MethodType type) {
- Invokers inv = METHOD_TYPE_FRIEND.getInvokers(type);
- if (inv != null) return inv;
- inv = new Invokers(type);
- METHOD_TYPE_FRIEND.setInvokers(type, inv);
- return inv;
+ /*non-public*/ void notifyGenericMethodType() {
+ if (genericInvoker != null) return;
+ try {
+ // Trigger adapter creation.
+ genericInvoker = InvokeGeneric.genericInvokerOf(erasedType);
+ } catch (Exception ex) {
+ Error err = new InternalError("Exception while resolving invokeGeneric");
+ err.initCause(ex);
+ throw err;
+ }
}
@Override
diff --git a/jdk/src/share/classes/java/dyn/MutableCallSite.java b/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java
similarity index 99%
rename from jdk/src/share/classes/java/dyn/MutableCallSite.java
rename to jdk/src/share/classes/java/lang/invoke/MutableCallSite.java
index 95df7a6a6d1..fe18237bb38 100644
--- a/jdk/src/share/classes/java/dyn/MutableCallSite.java
+++ b/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java
@@ -23,10 +23,8 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
-import sun.dyn.*;
-import sun.dyn.empty.Empty;
import java.util.concurrent.atomic.AtomicInteger;
/**
diff --git a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java b/jdk/src/share/classes/java/lang/invoke/SpreadGeneric.java
similarity index 98%
rename from jdk/src/share/classes/sun/dyn/SpreadGeneric.java
rename to jdk/src/share/classes/java/lang/invoke/SpreadGeneric.java
index 4c6a0800bcc..a862723e025 100644
--- a/jdk/src/share/classes/sun/dyn/SpreadGeneric.java
+++ b/jdk/src/share/classes/java/lang/invoke/SpreadGeneric.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,14 +23,14 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
+import sun.invoke.util.ValueConversions;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
-import sun.dyn.util.ValueConversions;
-import static sun.dyn.MemberName.newIllegalArgumentException;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* Generic spread adapter.
@@ -110,7 +110,7 @@ class SpreadGeneric {
static SpreadGeneric of(MethodType targetType, int spreadCount) {
if (targetType != targetType.generic())
throw new UnsupportedOperationException("NYI type="+targetType);
- MethodTypeImpl form = MethodTypeImpl.of(targetType);
+ MethodTypeForm form = targetType.form();
int outcount = form.parameterCount();
assert(spreadCount <= outcount);
SpreadGeneric[] spreadGens = form.spreadGeneric;
@@ -129,7 +129,7 @@ class SpreadGeneric {
// This mini-api is called from an Adapter to manage the spread.
/** A check/coercion that happens once before any selections. */
protected Object check(Object av, int n) {
- MethodHandleImpl.checkSpreadArgument(av, n);
+ checkSpreadArgument(av, n);
return av;
}
@@ -166,7 +166,7 @@ class SpreadGeneric {
// see if it has the required invoke method
MethodHandle entryPoint = null;
try {
- entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
} catch (ReflectiveOperationException ex) {
}
if (entryPoint == null) continue;
@@ -221,21 +221,21 @@ class SpreadGeneric {
@Override
public String toString() {
- return MethodHandleImpl.addTypeString(target, this);
+ return addTypeString(target, this);
}
static final MethodHandle NO_ENTRY = ValueConversions.identity();
protected boolean isPrototype() { return target == null; }
protected Adapter(SpreadGeneric outer) {
- super(Access.TOKEN, NO_ENTRY);
+ super(NO_ENTRY);
this.outer = outer;
this.target = null;
assert(isPrototype());
}
protected Adapter(SpreadGeneric outer, MethodHandle target) {
- super(Access.TOKEN, outer.entryPoint);
+ super(outer.entryPoint);
this.outer = outer;
this.target = target;
}
@@ -251,7 +251,7 @@ class SpreadGeneric {
return outer.select(av, n);
}
- static private final String CLASS_PREFIX; // "sun.dyn.SpreadGeneric$"
+ static private final String CLASS_PREFIX; // "java.lang.invoke.SpreadGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
diff --git a/jdk/src/share/classes/java/dyn/SwitchPoint.java b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java
similarity index 96%
rename from jdk/src/share/classes/java/dyn/SwitchPoint.java
rename to jdk/src/share/classes/java/lang/invoke/SwitchPoint.java
index 642e194b863..d81db187c88 100644
--- a/jdk/src/share/classes/java/dyn/SwitchPoint.java
+++ b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java
@@ -23,7 +23,7 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
/**
*
@@ -73,6 +73,10 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
* Switch points are useful without subclassing. They may also be subclassed.
* This may be useful in order to associate application-specific invalidation logic
* with the switch point.
+ * Notice that there is no permanent association between a switch point and
+ * the method handles it produces and consumes.
+ * The garbage collector may collect method handles produced or consumed
+ * by a switch point independently of the lifetime of the switch point itself.
*
* Implementation Note:
* A switch point behaves as if implemented on top of {@link MutableCallSite},
diff --git a/jdk/src/share/classes/sun/dyn/ToGeneric.java b/jdk/src/share/classes/java/lang/invoke/ToGeneric.java
similarity index 95%
rename from jdk/src/share/classes/sun/dyn/ToGeneric.java
rename to jdk/src/share/classes/java/lang/invoke/ToGeneric.java
index 38db3fea42f..22723975d5b 100644
--- a/jdk/src/share/classes/sun/dyn/ToGeneric.java
+++ b/jdk/src/share/classes/java/lang/invoke/ToGeneric.java
@@ -23,15 +23,14 @@
* questions.
*/
-package sun.dyn;
+package java.lang.invoke;
-import java.dyn.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MethodTypeImpl.invokers;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/**
* Adapters which mediate between incoming calls which are not generic
@@ -73,7 +72,7 @@ class ToGeneric {
assert(entryType.erase() == entryType); // for now
// incoming call will first "forget" all reference types except Object
this.entryType = entryType;
- MethodHandle invoker0 = invokers(entryType.generic()).exactInvoker();
+ MethodHandle invoker0 = entryType.generic().invokers().exactInvoker();
MethodType rawEntryTypeInit;
Adapter ad = findAdapter(rawEntryTypeInit = entryType);
if (ad != null) {
@@ -89,15 +88,15 @@ class ToGeneric {
}
// next, it will reorder primitives after references
- MethodType primsAtEnd = MethodTypeImpl.of(entryType).primsAtEnd();
+ MethodType primsAtEnd = entryType.form().primsAtEnd();
// at the same time, it will "forget" all primitive types except int/long
- this.primsAtEndOrder = MethodTypeImpl.primsAtEndOrder(entryType);
+ this.primsAtEndOrder = MethodTypeForm.primsAtEndOrder(entryType);
if (primsAtEndOrder != null) {
// reordering is required; build on top of a simpler ToGeneric
ToGeneric va2 = ToGeneric.of(primsAtEnd);
this.adapter = va2.adapter;
if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
- this.entryPoint = MethodHandleImpl.convertArguments(Access.TOKEN,
+ this.entryPoint = MethodHandleImpl.convertArguments(
va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
// example: for entryType of (int,Object,Object), the reordered
// type is (Object,Object,int) and the order is {1,2,0},
@@ -107,7 +106,7 @@ class ToGeneric {
// after any needed argument reordering, it will reinterpret
// primitive arguments according to their "raw" types int/long
- MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts();
+ MethodType intsAtEnd = primsAtEnd.form().primsAsInts();
ad = findAdapter(rawEntryTypeInit = intsAtEnd);
MethodHandle rawEntryPoint;
if (ad != null) {
@@ -116,7 +115,7 @@ class ToGeneric {
// Perhaps the adapter is available only for longs.
// If so, we can use it, but there will have to be a little
// more stack motion on each call.
- MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs();
+ MethodType longsAtEnd = primsAtEnd.form().primsAsLongs();
ad = findAdapter(rawEntryTypeInit = longsAtEnd);
if (ad != null) {
MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass());
@@ -128,7 +127,7 @@ class ToGeneric {
assert(midType.parameterType(i) == long.class);
assert(eptWithInts.parameterType(i) == int.class);
MethodType nextType = midType.changeParameterType(i, int.class);
- rawEntryPoint = MethodHandle.convertArguments(Access.TOKEN,
+ rawEntryPoint = MethodHandleImpl.convertArguments(
rawEntryPoint, nextType, midType, null);
midType = nextType;
}
@@ -143,7 +142,7 @@ class ToGeneric {
}
MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
this.entryPoint =
- AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, rawEntryPoint);
+ AdapterMethodHandle.makeRetypeRaw(tepType, rawEntryPoint);
if (this.entryPoint == null)
throw new UnsupportedOperationException("cannot retype to "+entryType
+" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
@@ -168,7 +167,7 @@ class ToGeneric {
assert(src.isPrimitive() && dst.isPrimitive());
if (filteredInvoker == null) {
filteredInvoker =
- AdapterMethodHandle.makeCheckCast(Access.TOKEN,
+ AdapterMethodHandle.makeCheckCast(
invoker.type().generic(), invoker, 0, MethodHandle.class);
if (filteredInvoker == null) throw new UnsupportedOperationException("NYI");
}
@@ -177,7 +176,7 @@ class ToGeneric {
if (filteredInvoker == null) throw new InternalError();
}
if (filteredInvoker == null) return invoker;
- return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker);
+ return AdapterMethodHandle.makeRetypeOnly(invoker.type(), filteredInvoker);
}
/**
@@ -227,7 +226,7 @@ class ToGeneric {
// retype erased reference arguments (the cast makes it safe to do this)
MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
MethodHandle typedEntryPoint =
- AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, entryPoint);
+ AdapterMethodHandle.makeRetypeRaw(tepType, entryPoint);
return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
}
@@ -248,7 +247,7 @@ class ToGeneric {
/** Return the adapter information for this type's erasure. */
static ToGeneric of(MethodType type) {
- MethodTypeImpl form = MethodTypeImpl.of(type);
+ MethodTypeForm form = type.form();
ToGeneric toGen = form.toGeneric;
if (toGen == null)
form.toGeneric = toGen = new ToGeneric(form.erasedType());
@@ -262,7 +261,7 @@ class ToGeneric {
/* Create an adapter for the given incoming call type. */
static Adapter findAdapter(MethodType entryPointType) {
- MethodTypeImpl form = MethodTypeImpl.of(entryPointType);
+ MethodTypeForm form = entryPointType.form();
Class> rtype = entryPointType.returnType();
int argc = form.parameterCount();
int lac = form.longPrimitiveParameterCount();
@@ -283,7 +282,7 @@ class ToGeneric {
for (String iname : inames) {
MethodHandle entryPoint = null;
try {
- entryPoint = MethodHandleImpl.IMPL_LOOKUP.
+ entryPoint = IMPL_LOOKUP.
findSpecial(acls, iname, entryPointType, acls);
} catch (ReflectiveOperationException ex) {
}
@@ -338,13 +337,13 @@ class ToGeneric {
@Override
public String toString() {
- return target == null ? "prototype:"+convert : MethodHandleImpl.addTypeString(target, this);
+ return target == null ? "prototype:"+convert : addTypeString(target, this);
}
protected boolean isPrototype() { return target == null; }
/* Prototype constructor. */
protected Adapter(MethodHandle entryPoint) {
- super(Access.TOKEN, entryPoint);
+ super(entryPoint);
this.invoker = null;
this.convert = entryPoint;
this.target = null;
@@ -356,7 +355,7 @@ class ToGeneric {
}
protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
- super(Access.TOKEN, entryPoint);
+ super(entryPoint);
this.invoker = invoker;
this.convert = convert;
this.target = target;
@@ -396,7 +395,7 @@ class ToGeneric {
protected float return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
- static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
+ static private final String CLASS_PREFIX; // "java.lang.invoke.ToGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
@@ -452,14 +451,15 @@ class genclasses {
static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
static String[][] TEMPLATES = { {
"@for@ arity=0..3 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
- "@for@ arity=4..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
+ "@for@ arity=4..4 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
+ "@for@ arity=5..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=6..10 rcat<=2 nrefs<=99 nints=0 nlongs<=99",
" //@each-cat@",
" static class @cat@ extends Adapter {",
" protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
" protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
- " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target, @av@); }",
+ " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target@comma@@av@); }",
" //@each-Tv@",
" protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
" //@end-Tv@",
@@ -471,7 +471,7 @@ class genclasses {
" }",
} };
enum VAR {
- cat, R, Rc, Tv, av, Tvav, Ovav;
+ cat, R, Rc, Tv, av, comma, Tvav, Ovav;
public final String pattern = "@"+toString().replace('_','.')+"@";
public String binding;
static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
@@ -493,12 +493,13 @@ class genclasses {
}
VAR.Tv.binding = comma(Tv);
VAR.av.binding = comma(av);
+ VAR.comma.binding = (av.length == 0 ? "" : ", ");
VAR.Tvav.binding = comma(Tvav);
VAR.Ovav.binding = comma(Ovav);
}
static String arg(int i) { return "a"+i; }
static String param(String t, String a) { return t+" "+a; }
- static String comma(String[] v) { return comma(v, ""); }
+ static String comma(String[] v) { return comma("", v); }
static String comma(String sep, String[] v) {
if (v.length == 0) return "";
String res = sep+v[0];
@@ -735,7 +736,7 @@ class genclasses {
protected float invoke_F(long a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(long a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
}
-//params=[4, 5, 2, 99, 99, 99]
+//params=[4, 4, 4, 99, 99, 99]
static class A4 extends Adapter {
protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
@@ -753,31 +754,50 @@ class genclasses {
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, int a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, int a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(int a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(int a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(int a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(int a0, int a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(int a0, int a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, long a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, long a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(long a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(long a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(long a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(long a0, long a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(long a0, long a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
}
+//params=[5, 5, 2, 99, 99, 99]
static class A5 extends Adapter {
protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
diff --git a/jdk/src/share/classes/java/dyn/VolatileCallSite.java b/jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java
similarity index 99%
rename from jdk/src/share/classes/java/dyn/VolatileCallSite.java
rename to jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java
index 616813ce2f5..de88f36bbb3 100644
--- a/jdk/src/share/classes/java/dyn/VolatileCallSite.java
+++ b/jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java
@@ -23,9 +23,7 @@
* questions.
*/
-package java.dyn;
-
-import java.util.List;
+package java.lang.invoke;
/**
* A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
diff --git a/jdk/src/share/classes/java/dyn/WrongMethodTypeException.java b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java
similarity index 96%
rename from jdk/src/share/classes/java/dyn/WrongMethodTypeException.java
rename to jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java
index 2455432e858..7d538dc8096 100644
--- a/jdk/src/share/classes/java/dyn/WrongMethodTypeException.java
+++ b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package java.dyn;
+package java.lang.invoke;
/**
* Thrown to indicate that code has attempted to call a method handle
diff --git a/jdk/src/share/classes/java/dyn/package-info.java b/jdk/src/share/classes/java/lang/invoke/package-info.java
similarity index 86%
rename from jdk/src/share/classes/java/dyn/package-info.java
rename to jdk/src/share/classes/java/lang/invoke/package-info.java
index d01c644f312..0eac856d218 100644
--- a/jdk/src/share/classes/java/dyn/package-info.java
+++ b/jdk/src/share/classes/java/lang/invoke/package-info.java
@@ -27,21 +27,18 @@
* The {@code java.lang.invoke} package contains dynamic language support provided directly by
* the Java core class libraries and virtual machine.
*
- *
- * Historic Note: In some early versions of Java SE 7,
- * the name of this package is {@code java.dyn}.
*
* Certain types in this package have special relations to dynamic
* language support in the virtual machine:
*
- * The class {@link java.dyn.MethodHandle MethodHandle} contains
+ * The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
* signature polymorphic methods
* which can be linked regardless of their type descriptor.
* Normally, method linkage requires exact matching of type descriptors.
*
*
* The JVM bytecode format supports immediate constants of
- * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
+ * the classes {@link java.lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke.MethodType MethodType}.
*
*
*
@@ -59,7 +56,7 @@
* with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
* The entry specifies the following information:
*
- * a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)
+ * a bootstrap method (a {@link java.lang.invoke.MethodHandle MethodHandle} constant)
* the dynamic invocation name (a UTF8 string)
* the argument and return types of the call (encoded as a type descriptor in a UTF8 string)
* optionally, a sequence of additional static arguments to the bootstrap method ({@code ldc}-type constants)
@@ -75,11 +72,6 @@
* A dynamic call site is linked by means of a bootstrap method,
* as described below .
*
- *
- * Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
- * instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
- * bootstrap method was specified dynamically, in a per-class basis, during class initialization.
- *
*
constant pool entries for {@code invokedynamic} instructions
* If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
* it must contain exactly four more bytes after the tag.
@@ -95,20 +87,20 @@
* except that the bootstrap method specifier reference replaces
* the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
*
- * constant pool entries for {@linkplain java.dyn.MethodType method types}
+ * constant pool entries for {@linkplain java.lang.invoke.MethodType method types}
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* entry which represents a method type descriptor.
*
* The JVM will ensure that on first
- * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
+ * execution of an {@code ldc} instruction for this entry, a {@link java.lang.invoke.MethodType MethodType}
* will be created which represents the type descriptor.
* Any classes mentioned in the {@code MethodType} will be loaded if necessary,
* but not initialized.
* Access checking and error reporting is performed exactly as it is for
* references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
*
- *
constant pool entries for {@linkplain java.dyn.MethodHandle method handles}
+ * constant pool entries for {@linkplain java.lang.invoke.MethodHandle method handles}
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
* it must contain exactly three more bytes. The first byte after the tag is a subtag
* value which must be in the range 1 through 9, and the last two must be an index to a
@@ -119,7 +111,7 @@
* must agree according to the table below.
*
* The JVM will ensure that on first execution of an {@code ldc} instruction
- * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
+ * for this entry, a {@link java.lang.invoke.MethodHandle MethodHandle} will be created which represents
* the field or method reference, according to the specific mode implied by the subtag.
*
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
@@ -135,23 +127,23 @@
*
* N subtag name member MH type bytecode behavior lookup expression
* 1 REF_getField C.f:T (C)T getfield C.f:T
- * {@linkplain java.dyn.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}
* 2 REF_getStatic C.f:T ( )T getstatic C.f:T
- * {@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}
* 3 REF_putField C.f:T (C,T)void putfield C.f:T
- * {@linkplain java.dyn.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}
* 4 REF_putStatic C.f:T (T)void putstatic C.f:T
- * {@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}
* 5 REF_invokeVirtual C.m(A*)T (C,A*)T invokevirtual C.m(A*)T
- * {@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}
* 6 REF_invokeStatic C.m(A*)T (C,A*)T invokestatic C.m(A*)T
- * {@linkplain java.dyn.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}
* 7 REF_invokeSpecial C.m(A*)T (C,A*)T invokespecial C.m(A*)T
- * {@linkplain java.dyn.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}
* 8 REF_newInvokeSpecial C.<init>(A*)void (A*)C new C; dup; invokespecial C.<init>(A*)void
- * {@linkplain java.dyn.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}
* 9 REF_invokeInterface C.m(A*)T (C,A*)T invokeinterface C.m(A*)T
- * {@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}
*
*
* Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
@@ -169,7 +161,7 @@
* and returns the same result (if any) as the corresponding bytecode behavior .
*
* Each method handle constant also has an equivalent reflective lookup expression ,
- * which is a query to a method in {@link java.dyn.MethodHandles.Lookup}.
+ * which is a query to a method in {@link java.lang.invoke.MethodHandles.Lookup}.
* In the example lookup method expression given in the table above, the name {@code MT}
* stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
* (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
@@ -191,7 +183,7 @@
* A constant may refer to a method or constructor with the {@code varargs}
* bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
* The method handle constant produced for such a method behaves as if
- * it were created by {@link java.dyn.MethodHandle#asVarargsCollector asVarargsCollector}.
+ * it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
* In other words, the constant method handle will exhibit variable arity,
* when invoked via {@code invokeGeneric}.
* On the other hand, its behavior with respect to {@code invokeExact} will be the same
@@ -225,7 +217,7 @@
* the call site must first be linked .
* Linking is accomplished by calling a bootstrap method
* which is given the static information content of the call site,
- * and which must produce a {@link java.dyn.MethodHandle method handle}
+ * and which must produce a {@link java.lang.invoke.MethodHandle method handle}
* that gives the behavior of the call site.
*
* Each {@code invokedynamic} instruction statically specifies its own
@@ -234,7 +226,7 @@
* just like {@code invokevirtual} and the other invoke instructions.
*
* Linking starts with resolving the constant pool entry for the
- * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
+ * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
* the type descriptor of the dynamic call site.
* This resolution process may trigger class loading.
* It may therefore throw an error if a class fails to load.
@@ -251,8 +243,8 @@
*
optionally, one or more additional static arguments
*
* The method handle is then applied to the other values as if by
- * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}.
- * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass).
+ * {@link java.lang.invoke.MethodHandle#invokeGeneric invokeGeneric}.
+ * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
* The type of the call site's target must be exactly equal to the type
* derived from the dynamic call site's type descriptor and passed to
* the bootstrap method.
@@ -263,18 +255,12 @@
* For example, the first argument could be {@code Object}
* instead of {@code MethodHandles.Lookup}, and the return type
* could also be {@code Object} instead of {@code CallSite}.
- *
- * As with any method handle constant, a {@code varargs} modifier bit
- * on the bootstrap method is ignored.
- *
- * Note that the first argument of the bootstrap method cannot be
- * a simple {@code Class} reference. (This is a change from earlier
- * versions of this specification. If the caller class is needed,
- * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
- * from the {@code Lookup} object.)
+ * (Note that the types and number of the stacked arguments limit
+ * the legal kinds of bootstrap methods to appropriately typed
+ * static methods and constructors of {@code CallSite} subclasses.)
*
* After resolution, the linkage process may fail in a variety of ways.
- * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
+ * All failures are reported by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
* which is thrown as the abnormal termination of the dynamic call
* site execution.
* The following circumstances will cause this:
@@ -290,7 +276,7 @@
*
the bootstrap method has a wrong argument or return type
* the bootstrap method invocation completes abnormally
* the result from the bootstrap invocation is not a reference to
- * an object of type {@link java.dyn.CallSite CallSite}
+ * an object of type {@link java.lang.invoke.CallSite CallSite}
* the target of the {@code CallSite} does not have a target of
* the expected {@code MethodType}
*
@@ -309,7 +295,7 @@
*
* In an application which requires dynamic call sites with individually
* mutable behaviors, their bootstrap methods should produce distinct
- * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
+ * {@link java.lang.invoke.CallSite CallSite} objects, one for each linkage request.
* Alternatively, an application can link a single {@code CallSite} object
* to several {@code invokedynamic} instructions, in which case
* a change to the target method will become visible at each of
@@ -322,11 +308,12 @@
* chosen target object.
*
*
- * Historic Note: Unlike some previous versions of this specification,
- * these rules do not enable the JVM to duplicate dynamic call sites,
+ * Discussion:
+ * These rules do not enable the JVM to duplicate dynamic call sites,
* or to issue “causeless” bootstrap method calls.
* Every dynamic call site transitions at most once from unlinked to linked,
* just before its first invocation.
+ * There is no way to undo the effect of a completed bootstrap method call.
*
*
* Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
@@ -354,7 +341,7 @@
*
* An {@code invokedynamic} instruction specifies at least three arguments
* to pass to its bootstrap method:
- * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object},
+ * The caller class (expressed as a {@link java.lang.invoke.MethodHandles.Lookup Lookup object},
* the name (extracted from the {@code CONSTANT_NameAndType} entry),
* and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
* The {@code invokedynamic} instruction may specify additional metadata values
@@ -382,8 +369,8 @@
* CONSTANT_Long java.lang.Longthe indexed long value
* CONSTANT_Float java.lang.Floatthe indexed float value
* CONSTANT_Double java.lang.Doublethe indexed double value
- * CONSTANT_MethodHandle java.dyn.MethodHandlethe indexed method handle constant
- * CONSTANT_MethodType java.dyn.MethodTypethe indexed method type constant
+ * CONSTANT_MethodHandle java.lang.invoke.MethodHandlethe indexed method handle constant
+ * CONSTANT_MethodType java.lang.invoke.MethodTypethe indexed method type constant
*
*
*
@@ -403,7 +390,7 @@
* then some or all of the arguments specified here may be collected into a trailing array parameter.
* (This is not a special rule, but rather a useful consequence of the interaction
* between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
- * and the {@code java.dyn.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
+ * and the {@code java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
*
* Given these rules, here are examples of legal bootstrap method declarations,
* given various numbers {@code N} of extra arguments.
@@ -436,7 +423,7 @@
* constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
* will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
* (If a string constant were passed instead, by badly generated code, that cast would then fail,
- * resulting in an {@code InvokeDynamicBootstrapError}.)
+ * resulting in a {@code BootstrapMethodError}.)
*
* Extra bootstrap method arguments are intended to allow language implementors
* to safely and compactly encode metadata.
@@ -473,6 +460,7 @@ struct BootstrapMethods_attr {
*
*
* @author John Rose, JSR 292 EG
+ * @since 1.7
*/
-package java.dyn;
+package java.lang.invoke;
diff --git a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
index 522fa3956b9..004cd408110 100644
--- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
@@ -28,6 +28,7 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Enumeration;
+import sun.net.ResourceManager;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -66,7 +67,14 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
*/
protected synchronized void create() throws SocketException {
fd = new FileDescriptor();
- datagramSocketCreate();
+ ResourceManager.beforeUdpCreate();
+ try {
+ datagramSocketCreate();
+ } catch (SocketException ioe) {
+ ResourceManager.afterUdpClose();
+ fd = null;
+ throw ioe;
+ }
}
/**
@@ -211,6 +219,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
protected void close() {
if (fd != null) {
datagramSocketClose();
+ ResourceManager.afterUdpClose();
fd = null;
}
}
diff --git a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
index 6d73cbc242c..f61fb34bdf1 100644
--- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
+++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
@@ -32,6 +32,7 @@ import java.io.FileDescriptor;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
+import sun.net.ResourceManager;
/**
* Default Socket Implementation. This implementation does
@@ -68,6 +69,10 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
private int resetState;
private final Object resetLock = new Object();
+ /* whether this Socket is a stream (TCP) socket or not (UDP)
+ */
+ private boolean stream;
+
/**
* Load net library into runtime.
*/
@@ -82,7 +87,19 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
*/
protected synchronized void create(boolean stream) throws IOException {
fd = new FileDescriptor();
- socketCreate(stream);
+ this.stream = stream;
+ if (!stream) {
+ ResourceManager.beforeUdpCreate();
+ try {
+ socketCreate(false);
+ } catch (IOException ioe) {
+ ResourceManager.afterUdpClose();
+ fd = null;
+ throw ioe;
+ }
+ } else {
+ socketCreate(true);
+ }
if (socket != null)
socket.setCreated();
if (serverSocket != null)
@@ -479,6 +496,9 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null) {
+ if (!stream) {
+ ResourceManager.afterUdpClose();
+ }
if (fdUseCount == 0) {
if (closePending) {
return;
diff --git a/jdk/src/share/classes/java/net/URI.java b/jdk/src/share/classes/java/net/URI.java
index 3465e1ab879..d1d9a87189a 100644
--- a/jdk/src/share/classes/java/net/URI.java
+++ b/jdk/src/share/classes/java/net/URI.java
@@ -1829,21 +1829,23 @@ public final class URI
} else if (authority != null) {
sb.append("//");
if (authority.startsWith("[")) {
+ // authority should (but may not) contain an embedded IPv6 address
int end = authority.indexOf("]");
- if (end != -1 && authority.indexOf(":")!=-1) {
- String doquote, dontquote;
+ String doquote = authority, dontquote = "";
+ if (end != -1 && authority.indexOf(":") != -1) {
+ // the authority contains an IPv6 address
if (end == authority.length()) {
dontquote = authority;
doquote = "";
} else {
- dontquote = authority.substring(0,end+1);
- doquote = authority.substring(end+1);
+ dontquote = authority.substring(0 , end + 1);
+ doquote = authority.substring(end + 1);
}
- sb.append (dontquote);
- sb.append(quote(doquote,
+ }
+ sb.append(dontquote);
+ sb.append(quote(doquote,
L_REG_NAME | L_SERVER,
H_REG_NAME | H_SERVER));
- }
} else {
sb.append(quote(authority,
L_REG_NAME | L_SERVER,
diff --git a/jdk/src/share/classes/java/net/URLConnection.java b/jdk/src/share/classes/java/net/URLConnection.java
index 6db1f6e82b3..976e8f66cea 100644
--- a/jdk/src/share/classes/java/net/URLConnection.java
+++ b/jdk/src/share/classes/java/net/URLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2011, 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
@@ -1422,7 +1422,7 @@ public abstract class URLConnection {
if (!is.markSupported())
return null;
- is.mark(12);
+ is.mark(16);
int c1 = is.read();
int c2 = is.read();
int c3 = is.read();
@@ -1434,6 +1434,11 @@ public abstract class URLConnection {
int c9 = is.read();
int c10 = is.read();
int c11 = is.read();
+ int c12 = is.read();
+ int c13 = is.read();
+ int c14 = is.read();
+ int c15 = is.read();
+ int c16 = is.read();
is.reset();
if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE) {
@@ -1461,6 +1466,13 @@ public abstract class URLConnection {
}
}
+ // big and little (identical) endian UTF-8 encodings, with BOM
+ if (c1 == 0xef && c2 == 0xbb && c3 == 0xbf) {
+ if (c4 == '<' && c5 == '?' && c6 == 'x') {
+ return "application/xml";
+ }
+ }
+
// big and little endian UTF-16 encodings, with byte order mark
if (c1 == 0xfe && c2 == 0xff) {
if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
@@ -1476,6 +1488,23 @@ public abstract class URLConnection {
}
}
+ // big and little endian UTF-32 encodings, with BOM
+ if (c1 == 0x00 && c2 == 0x00 && c3 == 0xfe && c4 == 0xff) {
+ if (c5 == 0 && c6 == 0 && c7 == 0 && c8 == '<' &&
+ c9 == 0 && c10 == 0 && c11 == 0 && c12 == '?' &&
+ c13 == 0 && c14 == 0 && c15 == 0 && c16 == 'x') {
+ return "application/xml";
+ }
+ }
+
+ if (c1 == 0xff && c2 == 0xfe && c3 == 0x00 && c4 == 0x00) {
+ if (c5 == '<' && c6 == 0 && c7 == 0 && c8 == 0 &&
+ c9 == '?' && c10 == 0 && c11 == 0 && c12 == 0 &&
+ c13 == 'x' && c14 == 0 && c15 == 0 && c16 == 0) {
+ return "application/xml";
+ }
+ }
+
if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
return "image/gif";
}
diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java
index 3e19ca3e515..8b7af13544c 100644
--- a/jdk/src/share/classes/java/nio/file/Files.java
+++ b/jdk/src/share/classes/java/nio/file/Files.java
@@ -1712,10 +1712,10 @@ public final class Files {
* @return the {@code path} parameter
*
* @throws UnsupportedOperationException
- * if the attribute view is not available or it does not support
- * updating the attribute
+ * if the attribute view is not available
* @throws IllegalArgumentException
- * if the attribute value is of the correct type but has an
+ * if the attribute name is not specified, or is not recognized, or
+ * the attribute value is of the correct type but has an
* inappropriate value
* @throws ClassCastException
* if the attribute value is not of the expected type or is a
@@ -1776,9 +1776,12 @@ public final class Files {
* @param options
* options indicating how symbolic links are handled
*
- * @return the attribute value or {@code null} if the attribute view
- * is not available or it does not support reading the attribute
+ * @return the attribute value
*
+ * @throws UnsupportedOperationException
+ * if the attribute view is not available
+ * @throws IllegalArgumentException
+ * if the attribute name is not specified or is not recognized
* @throws IOException
* if an I/O error occurs
* @throws SecurityException
@@ -1794,8 +1797,9 @@ public final class Files {
{
// only one attribute should be read
if (attribute.indexOf('*') >= 0 || attribute.indexOf(',') >= 0)
- return null;
+ throw new IllegalArgumentException(attribute);
Map map = readAttributes(path, attribute, options);
+ assert map.size() == 1;
String name;
int pos = attribute.indexOf(':');
if (pos == -1) {
@@ -1868,9 +1872,14 @@ public final class Files {
* @param options
* options indicating how symbolic links are handled
*
- * @return a map of the attributes returned; may be empty. The map's keys
- * are the attribute names, its values are the attribute values
+ * @return a map of the attributes returned; The map's keys are the
+ * attribute names, its values are the attribute values
*
+ * @throws UnsupportedOperationException
+ * if the attribute view is not available
+ * @throws IllegalArgumentException
+ * if no attributes are specified or an unrecognized attributes is
+ * specified
* @throws IOException
* if an I/O error occurs
* @throws SecurityException
diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java
index 85436b01d9a..618f0226363 100644
--- a/jdk/src/share/classes/java/nio/file/Path.java
+++ b/jdk/src/share/classes/java/nio/file/Path.java
@@ -228,6 +228,9 @@ public interface Path
* not have a root component and the given path has a root component then
* this path does not start with the given path.
*
+ * If the given path is associated with a different {@code FileSystem}
+ * to this path then {@code false} is returned.
+ *
* @param other
* the given path
*
@@ -270,6 +273,9 @@ public interface Path
* does not have a root component and the given path has a root component
* then this path does not end with the given path.
*
+ *
If the given path is associated with a different {@code FileSystem}
+ * to this path then {@code false} is returned.
+ *
* @param other
* the given path
*
@@ -283,7 +289,10 @@ public interface Path
* the given path string, in exactly the manner specified by the {@link
* #endsWith(Path) endsWith(Path)} method. On UNIX for example, the path
* "{@code foo/bar}" ends with "{@code foo/bar}" and "{@code bar}". It does
- * not end with "{@code r}" or "{@code /bar}".
+ * not end with "{@code r}" or "{@code /bar}". Note that trailing separators
+ * are not taken into account, and so invoking this method on the {@code
+ * Path}"{@code foo/bar}" with the {@code String} "{@code bar/}" returns
+ * {@code true}.
*
* @param other
* the given path string
@@ -724,12 +733,18 @@ public interface Path
* provider, platform specific. This method does not access the file system
* and neither file is required to exist.
*
+ *
This method may not be used to compare paths that are associated
+ * with different file system providers.
+ *
* @param other the path compared to this path.
*
* @return zero if the argument is {@link #equals equal} to this path, a
* value less than zero if this path is lexicographically less than
* the argument, or a value greater than zero if this path is
* lexicographically greater than the argument
+ *
+ * @throws ClassCastException
+ * if the paths are associated with different providers
*/
@Override
int compareTo(Path other);
@@ -738,7 +753,7 @@ public interface Path
* Tests this path for equality with the given object.
*
*
If the given object is not a Path, or is a Path associated with a
- * different provider, then this method immediately returns {@code false}.
+ * different {@code FileSystem}, then this method returns {@code false}.
*
*
Whether or not two path are equal depends on the file system
* implementation. In some cases the paths are compared without regard
diff --git a/jdk/src/share/classes/java/nio/file/WatchKey.java b/jdk/src/share/classes/java/nio/file/WatchKey.java
index 23897dba454..83403e96a3b 100644
--- a/jdk/src/share/classes/java/nio/file/WatchKey.java
+++ b/jdk/src/share/classes/java/nio/file/WatchKey.java
@@ -146,5 +146,5 @@ public interface WatchKey {
*
* @return the object for which this watch key was created
*/
- //T watchable();
+ Watchable watchable();
}
diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java
index 6cac437cdce..4e77b0e0172 100644
--- a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java
+++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java
@@ -216,12 +216,14 @@ public final class FileTime
* "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()}
* yields {@code "2009-02-13T23:31:30.123Z"}.
*
- *
A {@code FileTime} is primarly intended to represent the value of a
+ *
A {@code FileTime} is primarily intended to represent the value of a
* file's time stamp. Where used to represent extreme values , where
* the year is less than "{@code 0001}" or greater than "{@code 9999}" then
- * the year may be expanded to more than four digits and may be
- * negative-signed. If more than four digits then leading zeros are not
- * present. The year before "{@code 0001}" is "{@code -0001}".
+ * this method deviates from ISO 8601 in the same manner as the
+ * XML Schema
+ * language . That is, the year may be expanded to more than four digits
+ * and may be negative-signed. If more than four digits then leading zeros
+ * are not present. The year before "{@code 0001}" is "{@code -0001}".
*
* @return the string representation of this file time
*/
diff --git a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java
index ad285bd6ddb..8d43fb93769 100644
--- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java
+++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java
@@ -1037,6 +1037,11 @@ public abstract class FileSystemProvider {
* @return a map of the attributes returned; may be empty. The map's keys
* are the attribute names, its values are the attribute values
*
+ * @throws UnsupportedOperationException
+ * if the attribute view is not available
+ * @throws IllegalArgumentException
+ * if no attributes are specified or an unrecognized attributes is
+ * specified
* @throws IOException
* If an I/O error occurs
* @throws SecurityException
@@ -1064,10 +1069,10 @@ public abstract class FileSystemProvider {
* options indicating how symbolic links are handled
*
* @throws UnsupportedOperationException
- * if the attribute view is not available or it does not support
- * updating the attribute
+ * if the attribute view is not available
* @throws IllegalArgumentException
- * if the attribute value is of the correct type but has an
+ * if the attribute name is not specified, or is not recognized, or
+ * the attribute value is of the correct type but has an
* inappropriate value
* @throws ClassCastException
* If the attribute value is not of the expected type or is a
diff --git a/jdk/src/share/classes/java/security/AccessControlContext.java b/jdk/src/share/classes/java/security/AccessControlContext.java
index e80953b6696..940aff63770 100644
--- a/jdk/src/share/classes/java/security/AccessControlContext.java
+++ b/jdk/src/share/classes/java/security/AccessControlContext.java
@@ -29,6 +29,9 @@ import java.util.ArrayList;
import java.util.List;
import sun.security.util.Debug;
import sun.security.util.SecurityConstants;
+import sun.misc.JavaSecurityAccess;
+import sun.misc.SharedSecrets;
+
/**
* An AccessControlContext is used to make system resource access decisions
@@ -196,6 +199,24 @@ public final class AccessControlContext {
this.isPrivileged = isPrivileged;
}
+ /**
+ * Constructor for JavaSecurityAccess.doIntersectionPrivilege()
+ */
+ AccessControlContext(ProtectionDomain[] context,
+ AccessControlContext privilegedContext)
+ {
+ this.context = context;
+ this.privilegedContext = privilegedContext;
+ this.isPrivileged = true;
+ }
+
+ /**
+ * Returns this context's context.
+ */
+ ProtectionDomain[] getContext() {
+ return context;
+ }
+
/**
* Returns true if this context is privileged.
*/
diff --git a/jdk/src/share/classes/java/security/CodeSource.java b/jdk/src/share/classes/java/security/CodeSource.java
index 5ec8cebc028..b821a4ec9c1 100644
--- a/jdk/src/share/classes/java/security/CodeSource.java
+++ b/jdk/src/share/classes/java/security/CodeSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -578,7 +578,7 @@ public class CodeSource implements java.io.Serializable {
// Deserialize array of code signers (if any)
try {
- this.signers = (CodeSigner[])ois.readObject();
+ this.signers = ((CodeSigner[])ois.readObject()).clone();
} catch (IOException ioe) {
// no signers present
}
diff --git a/jdk/src/share/classes/java/security/ProtectionDomain.java b/jdk/src/share/classes/java/security/ProtectionDomain.java
index 43a39028e3d..9025e81b5dc 100644
--- a/jdk/src/share/classes/java/security/ProtectionDomain.java
+++ b/jdk/src/share/classes/java/security/ProtectionDomain.java
@@ -36,6 +36,8 @@ import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
import sun.misc.SharedSecrets;
import sun.security.util.Debug;
import sun.security.util.SecurityConstants;
+import sun.misc.JavaSecurityAccess;
+import sun.misc.SharedSecrets;
/**
*
@@ -59,6 +61,36 @@ import sun.security.util.SecurityConstants;
public class ProtectionDomain {
+ static {
+ // Set up JavaSecurityAccess in SharedSecrets
+ SharedSecrets.setJavaSecurityAccess(
+ new JavaSecurityAccess() {
+ public T doIntersectionPrivilege(
+ PrivilegedAction action,
+ final AccessControlContext stack,
+ final AccessControlContext context)
+ {
+ if (action == null) {
+ throw new NullPointerException();
+ }
+ return AccessController.doPrivileged(
+ action,
+ new AccessControlContext(
+ stack.getContext(), context).optimize()
+ );
+ }
+
+ public T doIntersectionPrivilege(
+ PrivilegedAction action,
+ AccessControlContext context)
+ {
+ return doIntersectionPrivilege(action,
+ AccessController.getContext(), context);
+ }
+ }
+ );
+ }
+
/* CodeSource */
private CodeSource codesource ;
diff --git a/jdk/src/share/classes/java/security/Timestamp.java b/jdk/src/share/classes/java/security/Timestamp.java
index 1629d9bbff9..f66d2883e62 100644
--- a/jdk/src/share/classes/java/security/Timestamp.java
+++ b/jdk/src/share/classes/java/security/Timestamp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -157,7 +157,8 @@ public final class Timestamp implements Serializable {
// Explicitly reset hash code value to -1
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
- ois.defaultReadObject();
- myhash = -1;
+ ois.defaultReadObject();
+ myhash = -1;
+ timestamp = new Date(timestamp.getTime());
}
}
diff --git a/jdk/src/share/classes/java/sql/DriverManager.java b/jdk/src/share/classes/java/sql/DriverManager.java
index 15273877dba..ce6c6bf4823 100644
--- a/jdk/src/share/classes/java/sql/DriverManager.java
+++ b/jdk/src/share/classes/java/sql/DriverManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -26,10 +26,10 @@
package java.sql;
import java.util.Iterator;
-import java.sql.Driver;
import java.util.ServiceLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -79,6 +79,27 @@ import java.security.PrivilegedAction;
public class DriverManager {
+ // List of registered JDBC drivers
+ private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList();
+ private static volatile int loginTimeout = 0;
+ private static volatile java.io.PrintWriter logWriter = null;
+ private static volatile java.io.PrintStream logStream = null;
+ // Used in println() to synchronize logWriter
+ private final static Object logSync = new Object();
+
+ /* Prevent the DriverManager class from being instantiated. */
+ private DriverManager(){}
+
+
+ /**
+ * Load the initial JDBC drivers by checking the System property
+ * jdbc.properties and then use the {@code ServiceLoader} mechanism
+ */
+ static {
+ loadInitialDrivers();
+ println("JDBC DriverManager initialized");
+ }
+
/**
* The SQLPermission constant that allows the
* setting of the logging stream.
@@ -235,44 +256,33 @@ public class DriverManager {
*/
public static Driver getDriver(String url)
throws SQLException {
- java.util.Vector drivers = null;
println("DriverManager.getDriver(\"" + url + "\")");
- if (!initialized) {
- initialize();
- }
-
- synchronized (DriverManager.class){
- // use the read copy of the drivers vector
- drivers = readDrivers;
- }
-
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
- // Walk through the loaded drivers attempting to locate someone
+ // Walk through the loaded registeredDrivers attempting to locate someone
// who understands the given URL.
- for (int i = 0; i < drivers.size(); i++) {
- DriverInfo di = (DriverInfo)drivers.elementAt(i);
+ for (Driver aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
- if ( getCallerClass(callerCL, di.driverClassName ) !=
- di.driverClass ) {
- println(" skipping: " + di);
- continue;
- }
- try {
- println(" trying " + di);
- if (di.driver.acceptsURL(url)) {
- // Success!
- println("getDriver returning " + di);
- return (di.driver);
+ if(isDriverAllowed(aDriver, callerCL)) {
+ try {
+ if(aDriver.acceptsURL(url)) {
+ // Success!
+ println("getDriver returning " + aDriver.getClass().getName());
+ return (aDriver);
+ }
+
+ } catch(SQLException sqe) {
+ // Drop through and try the next driver.
}
- } catch (SQLException ex) {
- // Drop through and try the next driver.
+ } else {
+ println(" skipping: " + aDriver.getClass().getName());
}
+
}
println("getDriver: no suitable driver");
@@ -292,23 +302,16 @@ public class DriverManager {
*/
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
- if (!initialized) {
- initialize();
+
+ /* Register the driver if it has not already been added to our list */
+ if(driver != null) {
+ registeredDrivers.addIfAbsent(driver);
+ } else {
+ // This is for compatibility with the original DriverManager
+ throw new NullPointerException();
}
- DriverInfo di = new DriverInfo();
-
- di.driver = driver;
- di.driverClass = driver.getClass();
- di.driverClassName = di.driverClass.getName();
-
- // Not Required -- drivers.addElement(di);
-
- writeDrivers.addElement(di);
- println("registerDriver: " + di);
-
- /* update the read copy of drivers vector */
- readDrivers = (java.util.Vector) writeDrivers.clone();
+ println("registerDriver: " + driver);
}
@@ -321,37 +324,26 @@ public class DriverManager {
*/
public static synchronized void deregisterDriver(Driver driver)
throws SQLException {
+ if (driver == null) {
+ return;
+ }
+
// Gets the classloader of the code that called this method,
// may be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
println("DriverManager.deregisterDriver: " + driver);
- // Walk through the loaded drivers.
- int i;
- DriverInfo di = null;
- for (i = 0; i < writeDrivers.size(); i++) {
- di = (DriverInfo)writeDrivers.elementAt(i);
- if (di.driver == driver) {
- break;
+ if(registeredDrivers.contains(driver)) {
+ if (isDriverAllowed(driver, callerCL)) {
+ registeredDrivers.remove(driver);
+ } else {
+ // If the caller does not have permission to load the driver then
+ // throw a SecurityException.
+ throw new SecurityException();
}
- }
- // If we can't find the driver just return.
- if (i >= writeDrivers.size()) {
+ } else {
println(" couldn't find driver to unload");
- return;
}
-
- // If the caller does not have permission to load the driver then
- // throw a security exception.
- if (getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
- throw new SecurityException();
- }
-
- // Remove the driver. Other entries in drivers get shuffled down.
- writeDrivers.removeElementAt(i);
-
- /* update the read copy of drivers vector */
- readDrivers = (java.util.Vector) writeDrivers.clone();
}
/**
@@ -364,34 +356,22 @@ public class DriverManager {
* @return the list of JDBC Drivers loaded by the caller's class loader
*/
public static java.util.Enumeration getDrivers() {
- java.util.Vector result = new java.util.Vector<>();
- java.util.Vector drivers = null;
-
- if (!initialized) {
- initialize();
- }
-
- synchronized (DriverManager.class){
- // use the readcopy of drivers
- drivers = readDrivers;
- }
+ java.util.Vector result = new java.util.Vector();
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
- // Walk through the loaded drivers.
- for (int i = 0; i < drivers.size(); i++) {
- DriverInfo di = (DriverInfo)drivers.elementAt(i);
+ // Walk through the loaded registeredDrivers.
+ for(Driver aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
- if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
- println(" skipping: " + di);
- continue;
+ if(isDriverAllowed(aDriver, callerCL)) {
+ result.addElement(aDriver);
+ } else {
+ println(" skipping: " + aDriver.getClass().getName());
}
- result.addElement(di.driver);
}
-
return (result.elements());
}
@@ -481,21 +461,22 @@ public class DriverManager {
//------------------------------------------------------------------------
- // Returns the class object that would be created if the code calling the
- // driver manager had loaded the driver class, or null if the class
- // is inaccessible.
- private static Class getCallerClass(ClassLoader callerClassLoader,
- String driverClassName) {
- Class callerC = null;
+ // Indicates whether the class object that would be created if the code calling
+ // DriverManager is accessible.
+ private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
+ boolean result = false;
+ if(driver != null) {
+ Class> aClass = null;
+ try {
+ aClass = Class.forName(driver.getClass().getName(), true, classLoader);
+ } catch (Exception ex) {
+ result = false;
+ }
- try {
- callerC = Class.forName(driverClassName, true, callerClassLoader);
- }
- catch (Exception ex) {
- callerC = null; // being very careful
+ result = ( aClass == driver.getClass() ) ? true : false;
}
- return callerC;
+ return result;
}
private static void loadInitialDrivers() {
@@ -544,26 +525,17 @@ public class DriverManager {
});
println("DriverManager.initialize: jdbc.drivers = " + drivers);
- if (drivers == null) {
+
+ if (drivers == null || drivers.equals("")) {
return;
}
- while (drivers.length() != 0) {
- int x = drivers.indexOf(':');
- String driver;
- if (x < 0) {
- driver = drivers;
- drivers = "";
- } else {
- driver = drivers.substring(0, x);
- drivers = drivers.substring(x+1);
- }
- if (driver.length() == 0) {
- continue;
- }
+ String[] driversList = drivers.split(":");
+ println("number of Drivers:" + driversList.length);
+ for (String aDriver : driversList) {
try {
- println("DriverManager.Initialize: loading " + driver);
- Class.forName(driver, true,
- ClassLoader.getSystemClassLoader());
+ println("DriverManager.Initialize: loading " + aDriver);
+ Class.forName(aDriver, true,
+ ClassLoader.getSystemClassLoader());
} catch (Exception ex) {
println("DriverManager.Initialize: load failed: " + ex);
}
@@ -574,7 +546,6 @@ public class DriverManager {
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
- java.util.Vector drivers = null;
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
@@ -594,40 +565,32 @@ public class DriverManager {
println("DriverManager.getConnection(\"" + url + "\")");
- if (!initialized) {
- initialize();
- }
-
- synchronized (DriverManager.class){
- // use the readcopy of drivers
- drivers = readDrivers;
- }
-
- // Walk through the loaded drivers attempting to make a connection.
+ // Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
- for (int i = 0; i < drivers.size(); i++) {
- DriverInfo di = (DriverInfo)drivers.elementAt(i);
+ for(Driver aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
- if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
- println(" skipping: " + di);
- continue;
- }
- try {
- println(" trying " + di);
- Connection result = di.driver.connect(url, info);
- if (result != null) {
- // Success!
- println("getConnection returning " + di);
- return (result);
- }
- } catch (SQLException ex) {
- if (reason == null) {
- reason = ex;
+ if(isDriverAllowed(aDriver, callerCL)) {
+ try {
+ println(" trying " + aDriver.getClass().getName());
+ Connection con = aDriver.connect(url, info);
+ if (con != null) {
+ // Success!
+ println("getConnection returning " + aDriver.getClass().getName());
+ return (con);
+ }
+ } catch (SQLException ex) {
+ if (reason == null) {
+ reason = ex;
+ }
}
+
+ } else {
+ println(" skipping: " + aDriver.getClass().getName());
}
+
}
// if we got here nobody could connect.
@@ -640,45 +603,7 @@ public class DriverManager {
throw new SQLException("No suitable driver found for "+ url, "08001");
}
-
- // Class initialization.
- static void initialize() {
- if (initialized) {
- return;
- }
- initialized = true;
- loadInitialDrivers();
- println("JDBC DriverManager initialized");
- }
-
- /* Prevent the DriverManager class from being instantiated. */
- private DriverManager(){}
-
- /* write copy of the drivers vector */
- private static java.util.Vector writeDrivers = new java.util.Vector();
-
- /* write copy of the drivers vector */
- private static java.util.Vector readDrivers = new java.util.Vector();
-
- private static int loginTimeout = 0;
- private static java.io.PrintWriter logWriter = null;
- private static java.io.PrintStream logStream = null;
- private static boolean initialized = false;
-
- private static Object logSync = new Object();
-
/* Returns the caller's class loader, or null if none */
private static native ClassLoader getCallerClassLoader();
}
-
-// DriverInfo is a package-private support class.
-class DriverInfo {
- Driver driver;
- Class driverClass;
- String driverClassName;
-
- public String toString() {
- return ("driver[className=" + driverClassName + "," + driver + "]");
- }
-}
diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java
index 797b9e2f8aa..6dcf8788052 100644
--- a/jdk/src/share/classes/java/util/Formatter.java
+++ b/jdk/src/share/classes/java/util/Formatter.java
@@ -1401,10 +1401,9 @@ import sun.misc.FormattedFloatingDecimal;
* The number of digits in the result for the fractional part of
* m or a is equal to the precision. If the precision is not
* specified then the default value is {@code 6}. If the precision is
- * less than the number of digits which would appear after the decimal
- * point in the string returned by {@link Float#toString(float)} or {@link
- * Double#toString(double)} respectively, then the value will be rounded
- * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
+ * less than the number of digits to the right of the decimal point then
+ * the value will be rounded using the
+ * {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
* algorithm}. Otherwise, zeros may be appended to reach the precision.
* For a canonical representation of the value, use {@link
* BigDecimal#toString()}.
@@ -1463,12 +1462,11 @@ import sun.misc.FormattedFloatingDecimal;
* more decimal digits representing the fractional part of m .
*
*
The number of digits in the result for the fractional part of
- * m or a is equal to the precision. If the precision is not
+ * m or a is equal to the precision. If the precision is not
* specified then the default value is {@code 6}. If the precision is
- * less than the number of digits which would appear after the decimal
- * point in the string returned by {@link Float#toString(float)} or {@link
- * Double#toString(double)} respectively, then the value will be rounded
- * using the {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
+ * less than the number of digits to the right of the decimal point
+ * then the value will be rounded using the
+ * {@linkplain java.math.BigDecimal#ROUND_HALF_UP round half up
* algorithm}. Otherwise, zeros may be appended to reach the precision.
* For a canonical representation of the value, use {@link
* BigDecimal#toString()}.
@@ -3585,7 +3583,7 @@ public final class Formatter implements Closeable, Flushable {
int scale = value.scale();
if (scale > prec) {
- // more "scale" digits than the requested "precision
+ // more "scale" digits than the requested "precision"
int compPrec = value.precision();
if (compPrec <= scale) {
// case of 0.xxxxxx
diff --git a/jdk/src/share/classes/java/util/JumboEnumSet.java b/jdk/src/share/classes/java/util/JumboEnumSet.java
index e3255963e56..398836a1c3b 100644
--- a/jdk/src/share/classes/java/util/JumboEnumSet.java
+++ b/jdk/src/share/classes/java/util/JumboEnumSet.java
@@ -34,6 +34,8 @@ package java.util;
* @serial exclude
*/
class JumboEnumSet> extends EnumSet {
+ private static final long serialVersionUID = 334349849919042784L;
+
/**
* Bit vector representation of this set. The ith bit of the jth
* element of this array represents the presence of universe[64*j +i]
@@ -138,8 +140,11 @@ class JumboEnumSet> extends EnumSet {
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
- elements[lastReturnedIndex] -= lastReturned;
- size--;
+ final long oldElements = elements[lastReturnedIndex];
+ elements[lastReturnedIndex] &= ~lastReturned;
+ if (oldElements != elements[lastReturnedIndex]) {
+ size--;
+ }
lastReturned = 0;
}
}
diff --git a/jdk/src/share/classes/java/util/Locale.java b/jdk/src/share/classes/java/util/Locale.java
index efe200ed0db..63c8b03c4d3 100644
--- a/jdk/src/share/classes/java/util/Locale.java
+++ b/jdk/src/share/classes/java/util/Locale.java
@@ -1168,7 +1168,7 @@ public final class Locale implements Cloneable, Serializable {
boolean e = (_extensions.getID().length() != 0);
StringBuilder result = new StringBuilder(_baseLocale.getLanguage());
- if (r || (l && v)) {
+ if (r || (l && (v || s || e))) {
result.append('_')
.append(_baseLocale.getRegion()); // This may just append '_'
}
diff --git a/jdk/src/share/classes/java/util/RegularEnumSet.java b/jdk/src/share/classes/java/util/RegularEnumSet.java
index c4f6215461b..a549fae2de1 100644
--- a/jdk/src/share/classes/java/util/RegularEnumSet.java
+++ b/jdk/src/share/classes/java/util/RegularEnumSet.java
@@ -34,6 +34,7 @@ package java.util;
* @serial exclude
*/
class RegularEnumSet> extends EnumSet {
+ private static final long serialVersionUID = 3411599620347842686L;
/**
* Bit vector representation of this set. The 2^k bit indicates the
* presence of universe[k] in this set.
@@ -106,7 +107,7 @@ class RegularEnumSet> extends EnumSet {
public void remove() {
if (lastReturned == 0)
throw new IllegalStateException();
- elements -= lastReturned;
+ elements &= ~lastReturned;
lastReturned = 0;
}
}
diff --git a/jdk/src/share/classes/java/util/TreeMap.java b/jdk/src/share/classes/java/util/TreeMap.java
index e256240f306..d14ee9f4b66 100644
--- a/jdk/src/share/classes/java/util/TreeMap.java
+++ b/jdk/src/share/classes/java/util/TreeMap.java
@@ -528,11 +528,8 @@ public class TreeMap
public V put(K key, V value) {
Entry t = root;
if (t == null) {
- // TBD:
- // 5045147: (coll) Adding null to an empty TreeSet should
- // throw NullPointerException
- //
- // compare(key, key); // type check
+ compare(key, key); // type (and possibly null) check
+
root = new Entry<>(key, value, null);
size = 1;
modCount++;
diff --git a/jdk/src/share/classes/java/util/UUID.java b/jdk/src/share/classes/java/util/UUID.java
index c2d3a3184d6..348c8686e0a 100644
--- a/jdk/src/share/classes/java/util/UUID.java
+++ b/jdk/src/share/classes/java/util/UUID.java
@@ -26,8 +26,6 @@
package java.util;
import java.security.*;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
/**
* A class that represents an immutable universally unique identifier (UUID).
@@ -90,36 +88,6 @@ public final class UUID implements java.io.Serializable, Comparable {
*/
private final long leastSigBits;
- /*
- * The version number associated with this UUID. Computed on demand.
- */
- private transient int version = -1;
-
- /*
- * The variant number associated with this UUID. Computed on demand.
- */
- private transient int variant = -1;
-
- /*
- * The timestamp associated with this UUID. Computed on demand.
- */
- private transient volatile long timestamp = -1;
-
- /*
- * The clock sequence associated with this UUID. Computed on demand.
- */
- private transient int sequence = -1;
-
- /*
- * The node number associated with this UUID. Computed on demand.
- */
- private transient long node = -1;
-
- /*
- * The hashcode of this UUID. Computed on demand.
- */
- private transient int hashCode = -1;
-
/*
* The random number generator used by this class to create random
* based UUIDs.
@@ -134,7 +102,7 @@ public final class UUID implements java.io.Serializable, Comparable {
private UUID(byte[] data) {
long msb = 0;
long lsb = 0;
- assert data.length == 16;
+ assert data.length == 16 : "data must be 16 bytes in length";
for (int i=0; i<8; i++)
msb = (msb << 8) | (data[i] & 0xff);
for (int i=8; i<16; i++)
@@ -276,11 +244,8 @@ public final class UUID implements java.io.Serializable, Comparable {
* @return The version number of this {@code UUID}
*/
public int version() {
- if (version < 0) {
- // Version is bits masked by 0x000000000000F000 in MS long
- version = (int)((mostSigBits >> 12) & 0x0f);
- }
- return version;
+ // Version is bits masked by 0x000000000000F000 in MS long
+ return (int)((mostSigBits >> 12) & 0x0f);
}
/**
@@ -298,17 +263,13 @@ public final class UUID implements java.io.Serializable, Comparable {
* @return The variant number of this {@code UUID}
*/
public int variant() {
- if (variant < 0) {
- // This field is composed of a varying number of bits
- if ((leastSigBits >>> 63) == 0) {
- variant = 0;
- } else if ((leastSigBits >>> 62) == 2) {
- variant = 2;
- } else {
- variant = (int)(leastSigBits >>> 61);
- }
- }
- return variant;
+ // This field is composed of a varying number of bits.
+ // 0 - - Reserved for NCS backward compatibility
+ // 1 0 - The Leach-Salz variant (used by this class)
+ // 1 1 0 Reserved, Microsoft backward compatibility
+ // 1 1 1 Reserved for future definition.
+ return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
+ & (leastSigBits >> 63));
}
/**
@@ -330,14 +291,10 @@ public final class UUID implements java.io.Serializable, Comparable {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
- long result = timestamp;
- if (result < 0) {
- result = (mostSigBits & 0x0000000000000FFFL) << 48;
- result |= ((mostSigBits >> 16) & 0xFFFFL) << 32;
- result |= mostSigBits >>> 32;
- timestamp = result;
- }
- return result;
+
+ return (mostSigBits & 0x0FFFL) << 48
+ | ((mostSigBits >> 16) & 0x0FFFFL) << 32
+ | mostSigBits >>> 32;
}
/**
@@ -360,10 +317,8 @@ public final class UUID implements java.io.Serializable, Comparable {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
- if (sequence < 0) {
- sequence = (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
- }
- return sequence;
+
+ return (int)((leastSigBits & 0x3FFF000000000000L) >>> 48);
}
/**
@@ -386,10 +341,8 @@ public final class UUID implements java.io.Serializable, Comparable {
if (version() != 1) {
throw new UnsupportedOperationException("Not a time-based UUID");
}
- if (node < 0) {
- node = leastSigBits & 0x0000FFFFFFFFFFFFL;
- }
- return node;
+
+ return leastSigBits & 0x0000FFFFFFFFFFFFL;
}
// Object Inherited Methods
@@ -438,13 +391,8 @@ public final class UUID implements java.io.Serializable, Comparable {
* @return A hash code value for this {@code UUID}
*/
public int hashCode() {
- if (hashCode == -1) {
- hashCode = (int)((mostSigBits >> 32) ^
- mostSigBits ^
- (leastSigBits >> 32) ^
- leastSigBits);
- }
- return hashCode;
+ long hilo = mostSigBits ^ leastSigBits;
+ return ((int)(hilo >> 32)) ^ (int) hilo;
}
/**
@@ -460,9 +408,7 @@ public final class UUID implements java.io.Serializable, Comparable {
* otherwise
*/
public boolean equals(Object obj) {
- if (!(obj instanceof UUID))
- return false;
- if (((UUID)obj).variant() != this.variant())
+ if ((null == obj) || (obj.getClass() != UUID.class))
return false;
UUID id = (UUID)obj;
return (mostSigBits == id.mostSigBits &&
@@ -494,23 +440,4 @@ public final class UUID implements java.io.Serializable, Comparable {
(this.leastSigBits > val.leastSigBits ? 1 :
0))));
}
-
- /**
- * Reconstitute the {@code UUID} instance from a stream (that is,
- * deserialize it). This is necessary to set the transient fields to their
- * correct uninitialized value so they will be recomputed on demand.
- */
- private void readObject(java.io.ObjectInputStream in)
- throws java.io.IOException, ClassNotFoundException {
-
- in.defaultReadObject();
-
- // Set "cached computation" fields to their initial values
- version = -1;
- variant = -1;
- timestamp = -1;
- sequence = -1;
- node = -1;
- hashCode = -1;
- }
}
diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
index f1b11140291..37d218f6775 100644
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
@@ -44,8 +44,8 @@ import java.util.concurrent.atomic.*;
* creation time, depending on which constructor is used.
*
* This class implements a concurrent variant of SkipLists providing
- * expected average log(n) time cost for the
+ * href="http://en.wikipedia.org/wiki/Skip_list" target="_top">SkipLists
+ * providing expected average log(n) time cost for the
* containsKey , get , put and
* remove operations and their variants. Insertion, removal,
* update, and access operations safely execute concurrently by
diff --git a/jdk/src/share/classes/java/util/concurrent/Exchanger.java b/jdk/src/share/classes/java/util/concurrent/Exchanger.java
index 8648278b755..e23f797c289 100644
--- a/jdk/src/share/classes/java/util/concurrent/Exchanger.java
+++ b/jdk/src/share/classes/java/util/concurrent/Exchanger.java
@@ -164,8 +164,8 @@ public class Exchanger {
* races between two threads or thread pre-emptions occurring
* between reading and CASing. Also, very transient peak
* contention can be much higher than the average sustainable
- * levels. The max limit is decreased on average 50% of the times
- * that a non-slot-zero wait elapses without being fulfilled.
+ * levels. An attempt to decrease the max limit is usually made
+ * when a non-slot-zero wait elapses without being fulfilled.
* Threads experiencing elapsed waits move closer to zero, so
* eventually find existing (or future) threads even if the table
* has been shrunk due to inactivity. The chosen mechanics and
diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
index 22938fe4ba9..e298d151c1b 100644
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -40,6 +40,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Random;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -51,6 +52,7 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Condition;
/**
* An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -158,239 +160,208 @@ public class ForkJoinPool extends AbstractExecutorService {
* set of worker threads: Submissions from non-FJ threads enter
* into a submission queue. Workers take these tasks and typically
* split them into subtasks that may be stolen by other workers.
- * The main work-stealing mechanics implemented in class
- * ForkJoinWorkerThread give first priority to processing tasks
- * from their own queues (LIFO or FIFO, depending on mode), then
- * to randomized FIFO steals of tasks in other worker queues, and
- * lastly to new submissions. These mechanics do not consider
- * affinities, loads, cache localities, etc, so rarely provide the
- * best possible performance on a given machine, but portably
- * provide good throughput by averaging over these factors.
- * (Further, even if we did try to use such information, we do not
- * usually have a basis for exploiting it. For example, some sets
- * of tasks profit from cache affinities, but others are harmed by
- * cache pollution effects.)
+ * Preference rules give first priority to processing tasks from
+ * their own queues (LIFO or FIFO, depending on mode), then to
+ * randomized FIFO steals of tasks in other worker queues, and
+ * lastly to new submissions.
*
- * Beyond work-stealing support and essential bookkeeping, the
- * main responsibility of this framework is to take actions when
- * one worker is waiting to join a task stolen (or always held by)
- * another. Because we are multiplexing many tasks on to a pool
- * of workers, we can't just let them block (as in Thread.join).
- * We also cannot just reassign the joiner's run-time stack with
- * another and replace it later, which would be a form of
- * "continuation", that even if possible is not necessarily a good
- * idea. Given that the creation costs of most threads on most
- * systems mainly surrounds setting up runtime stacks, thread
- * creation and switching is usually not much more expensive than
- * stack creation and switching, and is more flexible). Instead we
+ * The main throughput advantages of work-stealing stem from
+ * decentralized control -- workers mostly take tasks from
+ * themselves or each other. We cannot negate this in the
+ * implementation of other management responsibilities. The main
+ * tactic for avoiding bottlenecks is packing nearly all
+ * essentially atomic control state into a single 64bit volatile
+ * variable ("ctl"). This variable is read on the order of 10-100
+ * times as often as it is modified (always via CAS). (There is
+ * some additional control state, for example variable "shutdown"
+ * for which we can cope with uncoordinated updates.) This
+ * streamlines synchronization and control at the expense of messy
+ * constructions needed to repack status bits upon updates.
+ * Updates tend not to contend with each other except during
+ * bursts while submitted tasks begin or end. In some cases when
+ * they do contend, threads can instead do something else
+ * (usually, scan for tasks) until contention subsides.
+ *
+ * To enable packing, we restrict maximum parallelism to (1<<15)-1
+ * (which is far in excess of normal operating range) to allow
+ * ids, counts, and their negations (used for thresholding) to fit
+ * into 16bit fields.
+ *
+ * Recording Workers. Workers are recorded in the "workers" array
+ * that is created upon pool construction and expanded if (rarely)
+ * necessary. This is an array as opposed to some other data
+ * structure to support index-based random steals by workers.
+ * Updates to the array recording new workers and unrecording
+ * terminated ones are protected from each other by a seqLock
+ * (scanGuard) but the array is otherwise concurrently readable,
+ * and accessed directly by workers. To simplify index-based
+ * operations, the array size is always a power of two, and all
+ * readers must tolerate null slots. To avoid flailing during
+ * start-up, the array is presized to hold twice #parallelism
+ * workers (which is unlikely to need further resizing during
+ * execution). But to avoid dealing with so many null slots,
+ * variable scanGuard includes a mask for the nearest power of two
+ * that contains all current workers. All worker thread creation
+ * is on-demand, triggered by task submissions, replacement of
+ * terminated workers, and/or compensation for blocked
+ * workers. However, all other support code is set up to work with
+ * other policies. To ensure that we do not hold on to worker
+ * references that would prevent GC, ALL accesses to workers are
+ * via indices into the workers array (which is one source of some
+ * of the messy code constructions here). In essence, the workers
+ * array serves as a weak reference mechanism. Thus for example
+ * the wait queue field of ctl stores worker indices, not worker
+ * references. Access to the workers in associated methods (for
+ * example signalWork) must both index-check and null-check the
+ * IDs. All such accesses ignore bad IDs by returning out early
+ * from what they are doing, since this can only be associated
+ * with termination, in which case it is OK to give up.
+ *
+ * All uses of the workers array, as well as queue arrays, check
+ * that the array is non-null (even if previously non-null). This
+ * allows nulling during termination, which is currently not
+ * necessary, but remains an option for resource-revocation-based
+ * shutdown schemes.
+ *
+ * Wait Queuing. Unlike HPC work-stealing frameworks, we cannot
+ * let workers spin indefinitely scanning for tasks when none can
+ * be found immediately, and we cannot start/resume workers unless
+ * there appear to be tasks available. On the other hand, we must
+ * quickly prod them into action when new tasks are submitted or
+ * generated. We park/unpark workers after placing in an event
+ * wait queue when they cannot find work. This "queue" is actually
+ * a simple Treiber stack, headed by the "id" field of ctl, plus a
+ * 15bit counter value to both wake up waiters (by advancing their
+ * count) and avoid ABA effects. Successors are held in worker
+ * field "nextWait". Queuing deals with several intrinsic races,
+ * mainly that a task-producing thread can miss seeing (and
+ * signalling) another thread that gave up looking for work but
+ * has not yet entered the wait queue. We solve this by requiring
+ * a full sweep of all workers both before (in scan()) and after
+ * (in tryAwaitWork()) a newly waiting worker is added to the wait
+ * queue. During a rescan, the worker might release some other
+ * queued worker rather than itself, which has the same net
+ * effect. Because enqueued workers may actually be rescanning
+ * rather than waiting, we set and clear the "parked" field of
+ * ForkJoinWorkerThread to reduce unnecessary calls to unpark.
+ * (Use of the parked field requires a secondary recheck to avoid
+ * missed signals.)
+ *
+ * Signalling. We create or wake up workers only when there
+ * appears to be at least one task they might be able to find and
+ * execute. When a submission is added or another worker adds a
+ * task to a queue that previously had two or fewer tasks, they
+ * signal waiting workers (or trigger creation of new ones if
+ * fewer than the given parallelism level -- see signalWork).
+ * These primary signals are buttressed by signals during rescans
+ * as well as those performed when a worker steals a task and
+ * notices that there are more tasks too; together these cover the
+ * signals needed in cases when more than two tasks are pushed
+ * but untaken.
+ *
+ * Trimming workers. To release resources after periods of lack of
+ * use, a worker starting to wait when the pool is quiescent will
+ * time out and terminate if the pool has remained quiescent for
+ * SHRINK_RATE nanosecs. This will slowly propagate, eventually
+ * terminating all workers after long periods of non-use.
+ *
+ * Submissions. External submissions are maintained in an
+ * array-based queue that is structured identically to
+ * ForkJoinWorkerThread queues except for the use of
+ * submissionLock in method addSubmission. Unlike the case for
+ * worker queues, multiple external threads can add new
+ * submissions, so adding requires a lock.
+ *
+ * Compensation. Beyond work-stealing support and lifecycle
+ * control, the main responsibility of this framework is to take
+ * actions when one worker is waiting to join a task stolen (or
+ * always held by) another. Because we are multiplexing many
+ * tasks on to a pool of workers, we can't just let them block (as
+ * in Thread.join). We also cannot just reassign the joiner's
+ * run-time stack with another and replace it later, which would
+ * be a form of "continuation", that even if possible is not
+ * necessarily a good idea since we sometimes need both an
+ * unblocked task and its continuation to progress. Instead we
* combine two tactics:
*
* Helping: Arranging for the joiner to execute some task that it
* would be running if the steal had not occurred. Method
- * ForkJoinWorkerThread.helpJoinTask tracks joining->stealing
+ * ForkJoinWorkerThread.joinTask tracks joining->stealing
* links to try to find such a task.
*
* Compensating: Unless there are already enough live threads,
- * method helpMaintainParallelism() may create or
- * re-activate a spare thread to compensate for blocked
- * joiners until they unblock.
- *
- * It is impossible to keep exactly the target (parallelism)
- * number of threads running at any given time. Determining
- * existence of conservatively safe helping targets, the
- * availability of already-created spares, and the apparent need
- * to create new spares are all racy and require heuristic
- * guidance, so we rely on multiple retries of each. Compensation
- * occurs in slow-motion. It is triggered only upon timeouts of
- * Object.wait used for joins. This reduces poor decisions that
- * would otherwise be made when threads are waiting for others
- * that are stalled because of unrelated activities such as
- * garbage collection.
+ * method tryPreBlock() may create or re-activate a spare
+ * thread to compensate for blocked joiners until they
+ * unblock.
*
* The ManagedBlocker extension API can't use helping so relies
* only on compensation in method awaitBlocker.
*
- * The main throughput advantages of work-stealing stem from
- * decentralized control -- workers mostly steal tasks from each
- * other. We do not want to negate this by creating bottlenecks
- * implementing other management responsibilities. So we use a
- * collection of techniques that avoid, reduce, or cope well with
- * contention. These entail several instances of bit-packing into
- * CASable fields to maintain only the minimally required
- * atomicity. To enable such packing, we restrict maximum
- * parallelism to (1<<15)-1 (enabling twice this (to accommodate
- * unbalanced increments and decrements) to fit into a 16 bit
- * field, which is far in excess of normal operating range. Even
- * though updates to some of these bookkeeping fields do sometimes
- * contend with each other, they don't normally cache-contend with
- * updates to others enough to warrant memory padding or
- * isolation. So they are all held as fields of ForkJoinPool
- * objects. The main capabilities are as follows:
+ * It is impossible to keep exactly the target parallelism number
+ * of threads running at any given time. Determining the
+ * existence of conservatively safe helping targets, the
+ * availability of already-created spares, and the apparent need
+ * to create new spares are all racy and require heuristic
+ * guidance, so we rely on multiple retries of each. Currently,
+ * in keeping with on-demand signalling policy, we compensate only
+ * if blocking would leave less than one active (non-waiting,
+ * non-blocked) worker. Additionally, to avoid some false alarms
+ * due to GC, lagging counters, system activity, etc, compensated
+ * blocking for joins is only attempted after rechecks stabilize
+ * (retries are interspersed with Thread.yield, for good
+ * citizenship). The variable blockedCount, incremented before
+ * blocking and decremented after, is sometimes needed to
+ * distinguish cases of waiting for work vs blocking on joins or
+ * other managed sync. Both cases are equivalent for most pool
+ * control, so we can update non-atomically. (Additionally,
+ * contention on blockedCount alleviates some contention on ctl).
*
- * 1. Creating and removing workers. Workers are recorded in the
- * "workers" array. This is an array as opposed to some other data
- * structure to support index-based random steals by workers.
- * Updates to the array recording new workers and unrecording
- * terminated ones are protected from each other by a lock
- * (workerLock) but the array is otherwise concurrently readable,
- * and accessed directly by workers. To simplify index-based
- * operations, the array size is always a power of two, and all
- * readers must tolerate null slots. Currently, all worker thread
- * creation is on-demand, triggered by task submissions,
- * replacement of terminated workers, and/or compensation for
- * blocked workers. However, all other support code is set up to
- * work with other policies.
+ * Shutdown and Termination. A call to shutdownNow atomically sets
+ * the ctl stop bit and then (non-atomically) sets each workers
+ * "terminate" status, cancels all unprocessed tasks, and wakes up
+ * all waiting workers. Detecting whether termination should
+ * commence after a non-abrupt shutdown() call requires more work
+ * and bookkeeping. We need consensus about quiesence (i.e., that
+ * there is no more work) which is reflected in active counts so
+ * long as there are no current blockers, as well as possible
+ * re-evaluations during independent changes in blocking or
+ * quiescing workers.
*
- * To ensure that we do not hold on to worker references that
- * would prevent GC, ALL accesses to workers are via indices into
- * the workers array (which is one source of some of the unusual
- * code constructions here). In essence, the workers array serves
- * as a WeakReference mechanism. Thus for example the event queue
- * stores worker indices, not worker references. Access to the
- * workers in associated methods (for example releaseEventWaiters)
- * must both index-check and null-check the IDs. All such accesses
- * ignore bad IDs by returning out early from what they are doing,
- * since this can only be associated with shutdown, in which case
- * it is OK to give up. On termination, we just clobber these
- * data structures without trying to use them.
- *
- * 2. Bookkeeping for dynamically adding and removing workers. We
- * aim to approximately maintain the given level of parallelism.
- * When some workers are known to be blocked (on joins or via
- * ManagedBlocker), we may create or resume others to take their
- * place until they unblock (see below). Implementing this
- * requires counts of the number of "running" threads (i.e., those
- * that are neither blocked nor artificially suspended) as well as
- * the total number. These two values are packed into one field,
- * "workerCounts" because we need accurate snapshots when deciding
- * to create, resume or suspend. Note however that the
- * correspondence of these counts to reality is not guaranteed. In
- * particular updates for unblocked threads may lag until they
- * actually wake up.
- *
- * 3. Maintaining global run state. The run state of the pool
- * consists of a runLevel (SHUTDOWN, TERMINATING, etc) similar to
- * those in other Executor implementations, as well as a count of
- * "active" workers -- those that are, or soon will be, or
- * recently were executing tasks. The runLevel and active count
- * are packed together in order to correctly trigger shutdown and
- * termination. Without care, active counts can be subject to very
- * high contention. We substantially reduce this contention by
- * relaxing update rules. A worker must claim active status
- * prospectively, by activating if it sees that a submitted or
- * stealable task exists (it may find after activating that the
- * task no longer exists). It stays active while processing this
- * task (if it exists) and any other local subtasks it produces,
- * until it cannot find any other tasks. It then tries
- * inactivating (see method preStep), but upon update contention
- * instead scans for more tasks, later retrying inactivation if it
- * doesn't find any.
- *
- * 4. Managing idle workers waiting for tasks. We cannot let
- * workers spin indefinitely scanning for tasks when none are
- * available. On the other hand, we must quickly prod them into
- * action when new tasks are submitted or generated. We
- * park/unpark these idle workers using an event-count scheme.
- * Field eventCount is incremented upon events that may enable
- * workers that previously could not find a task to now find one:
- * Submission of a new task to the pool, or another worker pushing
- * a task onto a previously empty queue. (We also use this
- * mechanism for configuration and termination actions that
- * require wakeups of idle workers). Each worker maintains its
- * last known event count, and blocks when a scan for work did not
- * find a task AND its lastEventCount matches the current
- * eventCount. Waiting idle workers are recorded in a variant of
- * Treiber stack headed by field eventWaiters which, when nonzero,
- * encodes the thread index and count awaited for by the worker
- * thread most recently calling eventSync. This thread in turn has
- * a record (field nextEventWaiter) for the next waiting worker.
- * In addition to allowing simpler decisions about need for
- * wakeup, the event count bits in eventWaiters serve the role of
- * tags to avoid ABA errors in Treiber stacks. Upon any wakeup,
- * released threads also try to release at most two others. The
- * net effect is a tree-like diffusion of signals, where released
- * threads (and possibly others) help with unparks. To further
- * reduce contention effects a bit, failed CASes to increment
- * field eventCount are tolerated without retries in signalWork.
- * Conceptually they are merged into the same event, which is OK
- * when their only purpose is to enable workers to scan for work.
- *
- * 5. Managing suspension of extra workers. When a worker notices
- * (usually upon timeout of a wait()) that there are too few
- * running threads, we may create a new thread to maintain
- * parallelism level, or at least avoid starvation. Usually, extra
- * threads are needed for only very short periods, yet join
- * dependencies are such that we sometimes need them in
- * bursts. Rather than create new threads each time this happens,
- * we suspend no-longer-needed extra ones as "spares". For most
- * purposes, we don't distinguish "extra" spare threads from
- * normal "core" threads: On each call to preStep (the only point
- * at which we can do this) a worker checks to see if there are
- * now too many running workers, and if so, suspends itself.
- * Method helpMaintainParallelism looks for suspended threads to
- * resume before considering creating a new replacement. The
- * spares themselves are encoded on another variant of a Treiber
- * Stack, headed at field "spareWaiters". Note that the use of
- * spares is intrinsically racy. One thread may become a spare at
- * about the same time as another is needlessly being created. We
- * counteract this and related slop in part by requiring resumed
- * spares to immediately recheck (in preStep) to see whether they
- * should re-suspend.
- *
- * 6. Killing off unneeded workers. A timeout mechanism is used to
- * shed unused workers: The oldest (first) event queue waiter uses
- * a timed rather than hard wait. When this wait times out without
- * a normal wakeup, it tries to shutdown any one (for convenience
- * the newest) other spare or event waiter via
- * tryShutdownUnusedWorker. This eventually reduces the number of
- * worker threads to a minimum of one after a long enough period
- * without use.
- *
- * 7. Deciding when to create new workers. The main dynamic
- * control in this class is deciding when to create extra threads
- * in method helpMaintainParallelism. We would like to keep
- * exactly #parallelism threads running, which is an impossible
- * task. We always need to create one when the number of running
- * threads would become zero and all workers are busy. Beyond
- * this, we must rely on heuristics that work well in the
- * presence of transient phenomena such as GC stalls, dynamic
- * compilation, and wake-up lags. These transients are extremely
- * common -- we are normally trying to fully saturate the CPUs on
- * a machine, so almost any activity other than running tasks
- * impedes accuracy. Our main defense is to allow parallelism to
- * lapse for a while during joins, and use a timeout to see if,
- * after the resulting settling, there is still a need for
- * additional workers. This also better copes with the fact that
- * some of the methods in this class tend to never become compiled
- * (but are interpreted), so some components of the entire set of
- * controls might execute 100 times faster than others. And
- * similarly for cases where the apparent lack of work is just due
- * to GC stalls and other transient system activity.
- *
- * Beware that there is a lot of representation-level coupling
+ * Style notes: There is a lot of representation-level coupling
* among classes ForkJoinPool, ForkJoinWorkerThread, and
- * ForkJoinTask. For example, direct access to "workers" array by
+ * ForkJoinTask. Most fields of ForkJoinWorkerThread maintain
+ * data structures managed by ForkJoinPool, so are directly
+ * accessed. Conversely we allow access to "workers" array by
* workers, and direct access to ForkJoinTask.status by both
* ForkJoinPool and ForkJoinWorkerThread. There is little point
* trying to reduce this, since any associated future changes in
* representations will need to be accompanied by algorithmic
- * changes anyway.
+ * changes anyway. All together, these low-level implementation
+ * choices produce as much as a factor of 4 performance
+ * improvement compared to naive implementations, and enable the
+ * processing of billions of tasks per second, at the expense of
+ * some ugliness.
*
- * Style notes: There are lots of inline assignments (of form
- * "while ((local = field) != 0)") which are usually the simplest
- * way to ensure the required read orderings (which are sometimes
- * critical). Also several occurrences of the unusual "do {}
- * while (!cas...)" which is the simplest way to force an update of
- * a CAS'ed variable. There are also other coding oddities that
- * help some methods perform reasonably even when interpreted (not
- * compiled), at the expense of some messy constructions that
- * reduce byte code counts.
+ * Methods signalWork() and scan() are the main bottlenecks so are
+ * especially heavily micro-optimized/mangled. There are lots of
+ * inline assignments (of form "while ((local = field) != 0)")
+ * which are usually the simplest way to ensure the required read
+ * orderings (which are sometimes critical). This leads to a
+ * "C"-like style of listing declarations of these locals at the
+ * heads of methods or blocks. There are several occurrences of
+ * the unusual "do {} while (!cas...)" which is the simplest way
+ * to force an update of a CAS'ed variable. There are also other
+ * coding oddities that help some methods perform reasonably even
+ * when interpreted (not compiled).
*
- * The order of declarations in this file is: (1) statics (2)
- * fields (along with constants used when unpacking some of them)
- * (3) internal control methods (4) callbacks and other support
- * for ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
- * methods (plus a few little helpers).
+ * The order of declarations in this file is: (1) declarations of
+ * statics (2) fields (along with constants used when unpacking
+ * some of them), listed in an order that tends to reduce
+ * contention among them a bit under most JVMs. (3) internal
+ * control methods (4) callbacks and other support for
+ * ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
+ * methods (plus a few little helpers). (6) static block
+ * initializing all statics in a minimally dependent order.
*/
/**
@@ -425,15 +396,13 @@ public class ForkJoinPool extends AbstractExecutorService {
* overridden in ForkJoinPool constructors.
*/
public static final ForkJoinWorkerThreadFactory
- defaultForkJoinWorkerThreadFactory =
- new DefaultForkJoinWorkerThreadFactory();
+ defaultForkJoinWorkerThreadFactory;
/**
* Permission required for callers of methods that may start or
* kill threads.
*/
- private static final RuntimePermission modifyThreadPermission =
- new RuntimePermission("modifyThread");
+ private static final RuntimePermission modifyThreadPermission;
/**
* If there is a security manager, makes sure caller has
@@ -448,69 +417,76 @@ public class ForkJoinPool extends AbstractExecutorService {
/**
* Generator for assigning sequence numbers as pool names.
*/
- private static final AtomicInteger poolNumberGenerator =
- new AtomicInteger();
+ private static final AtomicInteger poolNumberGenerator;
/**
- * The time to block in a join (see awaitJoin) before checking if
- * a new worker should be (re)started to maintain parallelism
- * level. The value should be short enough to maintain global
- * responsiveness and progress but long enough to avoid
- * counterproductive firings during GC stalls or unrelated system
- * activity, and to not bog down systems with continual re-firings
- * on GCs or legitimately long waits.
+ * Generator for initial random seeds for worker victim
+ * selection. This is used only to create initial seeds. Random
+ * steals use a cheaper xorshift generator per steal attempt. We
+ * don't expect much contention on seedGenerator, so just use a
+ * plain Random.
*/
- private static final long JOIN_TIMEOUT_MILLIS = 250L; // 4 per second
+ static final Random workerSeedGenerator;
/**
- * The wakeup interval (in nanoseconds) for the oldest worker
- * waiting for an event to invoke tryShutdownUnusedWorker to
- * shrink the number of workers. The exact value does not matter
- * too much. It must be short enough to release resources during
- * sustained periods of idleness, but not so short that threads
- * are continually re-created.
+ * Array holding all worker threads in the pool. Initialized upon
+ * construction. Array size must be a power of two. Updates and
+ * replacements are protected by scanGuard, but the array is
+ * always kept in a consistent enough state to be randomly
+ * accessed without locking by workers performing work-stealing,
+ * as well as other traversal-based methods in this class, so long
+ * as reads memory-acquire by first reading ctl. All readers must
+ * tolerate that some array slots may be null.
*/
- private static final long SHRINK_RATE_NANOS =
- 30L * 1000L * 1000L * 1000L; // 2 per minute
+ ForkJoinWorkerThread[] workers;
/**
- * Absolute bound for parallelism level. Twice this number plus
- * one (i.e., 0xfff) must fit into a 16bit field to enable
- * word-packing for some counts and indices.
+ * Initial size for submission queue array. Must be a power of
+ * two. In many applications, these always stay small so we use a
+ * small initial cap.
*/
- private static final int MAX_WORKERS = 0x7fff;
+ private static final int INITIAL_QUEUE_CAPACITY = 8;
/**
- * Array holding all worker threads in the pool. Array size must
- * be a power of two. Updates and replacements are protected by
- * workerLock, but the array is always kept in a consistent enough
- * state to be randomly accessed without locking by workers
- * performing work-stealing, as well as other traversal-based
- * methods in this class. All readers must tolerate that some
- * array slots may be null.
+ * Maximum size for submission queue array. Must be a power of two
+ * less than or equal to 1 << (31 - width of array entry) to
+ * ensure lack of index wraparound, but is capped at a lower
+ * value to help users trap runaway computations.
*/
- volatile ForkJoinWorkerThread[] workers;
+ private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
/**
- * Queue for external submissions.
+ * Array serving as submission queue. Initialized upon construction.
*/
- private final LinkedTransferQueue> submissionQueue;
+ private ForkJoinTask>[] submissionQueue;
/**
- * Lock protecting updates to workers array.
+ * Lock protecting submissions array for addSubmission
*/
- private final ReentrantLock workerLock;
+ private final ReentrantLock submissionLock;
/**
- * Latch released upon termination.
+ * Condition for awaitTermination, using submissionLock for
+ * convenience.
*/
- private final Phaser termination;
+ private final Condition termination;
/**
* Creation factory for worker threads.
*/
private final ForkJoinWorkerThreadFactory factory;
+ /**
+ * The uncaught exception handler used when any worker abruptly
+ * terminates.
+ */
+ final Thread.UncaughtExceptionHandler ueh;
+
+ /**
+ * Prefix for assigning names to worker threads
+ */
+ private final String workerNamePrefix;
+
/**
* Sum of per-thread steal counts, updated only when threads are
* idle or terminating.
@@ -518,82 +494,87 @@ public class ForkJoinPool extends AbstractExecutorService {
private volatile long stealCount;
/**
- * Encoded record of top of Treiber stack of threads waiting for
- * events. The top 32 bits contain the count being waited for. The
- * bottom 16 bits contains one plus the pool index of waiting
- * worker thread. (Bits 16-31 are unused.)
- */
- private volatile long eventWaiters;
-
- private static final int EVENT_COUNT_SHIFT = 32;
- private static final int WAITER_ID_MASK = (1 << 16) - 1;
-
- /**
- * A counter for events that may wake up worker threads:
- * - Submission of a new task to the pool
- * - A worker pushing a task on an empty queue
- * - termination
- */
- private volatile int eventCount;
-
- /**
- * Encoded record of top of Treiber stack of spare threads waiting
- * for resumption. The top 16 bits contain an arbitrary count to
- * avoid ABA effects. The bottom 16bits contains one plus the pool
- * index of waiting worker thread.
- */
- private volatile int spareWaiters;
-
- private static final int SPARE_COUNT_SHIFT = 16;
- private static final int SPARE_ID_MASK = (1 << 16) - 1;
-
- /**
- * Lifecycle control. The low word contains the number of workers
- * that are (probably) executing tasks. This value is atomically
- * incremented before a worker gets a task to run, and decremented
- * when a worker has no tasks and cannot find any. Bits 16-18
- * contain runLevel value. When all are zero, the pool is
- * running. Level transitions are monotonic (running -> shutdown
- * -> terminating -> terminated) so each transition adds a bit.
- * These are bundled together to ensure consistent read for
- * termination checks (i.e., that runLevel is at least SHUTDOWN
- * and active threads is zero).
+ * Main pool control -- a long packed with:
+ * AC: Number of active running workers minus target parallelism (16 bits)
+ * TC: Number of total workers minus target parallelism (16bits)
+ * ST: true if pool is terminating (1 bit)
+ * EC: the wait count of top waiting thread (15 bits)
+ * ID: ~poolIndex of top of Treiber stack of waiting threads (16 bits)
*
- * Notes: Most direct CASes are dependent on these bitfield
- * positions. Also, this field is non-private to enable direct
- * performance-sensitive CASes in ForkJoinWorkerThread.
+ * When convenient, we can extract the upper 32 bits of counts and
+ * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
+ * (int)ctl. The ec field is never accessed alone, but always
+ * together with id and st. The offsets of counts by the target
+ * parallelism and the positionings of fields makes it possible to
+ * perform the most common checks via sign tests of fields: When
+ * ac is negative, there are not enough active workers, when tc is
+ * negative, there are not enough total workers, when id is
+ * negative, there is at least one waiting worker, and when e is
+ * negative, the pool is terminating. To deal with these possibly
+ * negative fields, we use casts in and out of "short" and/or
+ * signed shifts to maintain signedness.
*/
- volatile int runState;
+ volatile long ctl;
- // Note: The order among run level values matters.
- private static final int RUNLEVEL_SHIFT = 16;
- private static final int SHUTDOWN = 1 << RUNLEVEL_SHIFT;
- private static final int TERMINATING = 1 << (RUNLEVEL_SHIFT + 1);
- private static final int TERMINATED = 1 << (RUNLEVEL_SHIFT + 2);
- private static final int ACTIVE_COUNT_MASK = (1 << RUNLEVEL_SHIFT) - 1;
+ // bit positions/shifts for fields
+ private static final int AC_SHIFT = 48;
+ private static final int TC_SHIFT = 32;
+ private static final int ST_SHIFT = 31;
+ private static final int EC_SHIFT = 16;
- /**
- * Holds number of total (i.e., created and not yet terminated)
- * and running (i.e., not blocked on joins or other managed sync)
- * threads, packed together to ensure consistent snapshot when
- * making decisions about creating and suspending spare
- * threads. Updated only by CAS. Note that adding a new worker
- * requires incrementing both counts, since workers start off in
- * running state.
- */
- private volatile int workerCounts;
+ // bounds
+ private static final int MAX_ID = 0x7fff; // max poolIndex
+ private static final int SMASK = 0xffff; // mask short bits
+ private static final int SHORT_SIGN = 1 << 15;
+ private static final int INT_SIGN = 1 << 31;
- private static final int TOTAL_COUNT_SHIFT = 16;
- private static final int RUNNING_COUNT_MASK = (1 << TOTAL_COUNT_SHIFT) - 1;
- private static final int ONE_RUNNING = 1;
- private static final int ONE_TOTAL = 1 << TOTAL_COUNT_SHIFT;
+ // masks
+ private static final long STOP_BIT = 0x0001L << ST_SHIFT;
+ private static final long AC_MASK = ((long)SMASK) << AC_SHIFT;
+ private static final long TC_MASK = ((long)SMASK) << TC_SHIFT;
+
+ // units for incrementing and decrementing
+ private static final long TC_UNIT = 1L << TC_SHIFT;
+ private static final long AC_UNIT = 1L << AC_SHIFT;
+
+ // masks and units for dealing with u = (int)(ctl >>> 32)
+ private static final int UAC_SHIFT = AC_SHIFT - 32;
+ private static final int UTC_SHIFT = TC_SHIFT - 32;
+ private static final int UAC_MASK = SMASK << UAC_SHIFT;
+ private static final int UTC_MASK = SMASK << UTC_SHIFT;
+ private static final int UAC_UNIT = 1 << UAC_SHIFT;
+ private static final int UTC_UNIT = 1 << UTC_SHIFT;
+
+ // masks and units for dealing with e = (int)ctl
+ private static final int E_MASK = 0x7fffffff; // no STOP_BIT
+ private static final int EC_UNIT = 1 << EC_SHIFT;
/**
* The target parallelism level.
- * Accessed directly by ForkJoinWorkerThreads.
*/
final int parallelism;
+ /**
+ * Index (mod submission queue length) of next element to take
+ * from submission queue. Usage is identical to that for
+ * per-worker queues -- see ForkJoinWorkerThread internal
+ * documentation.
+ */
+ volatile int queueBase;
+
+ /**
+ * Index (mod submission queue length) of next element to add
+ * in submission queue. Usage is identical to that for
+ * per-worker queues -- see ForkJoinWorkerThread internal
+ * documentation.
+ */
+ int queueTop;
+
+ /**
+ * True when shutdown() has been called.
+ */
+ volatile boolean shutdown;
+
/**
* True if use local fifo, not default lifo, for local polling
* Read by, and replicated by ForkJoinWorkerThreads
@@ -601,139 +582,615 @@ public class ForkJoinPool extends AbstractExecutorService {
final boolean locallyFifo;
/**
- * The uncaught exception handler used when any worker abruptly
- * terminates.
+ * The number of threads in ForkJoinWorkerThreads.helpQuiescePool.
+ * When non-zero, suppresses automatic shutdown when active
+ * counts become zero.
*/
- private final Thread.UncaughtExceptionHandler ueh;
+ volatile int quiescerCount;
/**
- * Pool number, just for assigning useful names to worker threads
+ * The number of threads blocked in join.
*/
- private final int poolNumber;
-
- // Utilities for CASing fields. Note that most of these
- // are usually manually inlined by callers
+ volatile int blockedCount;
/**
- * Increments running count part of workerCounts.
+ * Counter for worker Thread names (unrelated to their poolIndex)
*/
- final void incrementRunningCount() {
- int c;
- do {} while (!UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- c = workerCounts,
- c + ONE_RUNNING));
- }
+ private volatile int nextWorkerNumber;
/**
- * Tries to increment running count part of workerCounts.
+ * The index for the next created worker. Accessed under scanGuard.
*/
- final boolean tryIncrementRunningCount() {
- int c;
- return UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- c = workerCounts,
- c + ONE_RUNNING);
- }
+ private int nextWorkerIndex;
/**
- * Tries to decrement running count unless already zero.
+ * SeqLock and index masking for updates to workers array. Locked
+ * when SG_UNIT is set. Unlocking clears bit by adding
+ * SG_UNIT. Staleness of read-only operations can be checked by
+ * comparing scanGuard to value before the reads. The low 16 bits
+ * (i.e, anding with SMASK) hold (the smallest power of two
+ * covering all worker indices, minus one, and is used to avoid
+ * dealing with large numbers of null slots when the workers array
+ * is overallocated.
*/
- final boolean tryDecrementRunningCount() {
- int wc = workerCounts;
- if ((wc & RUNNING_COUNT_MASK) == 0)
- return false;
- return UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING);
- }
+ volatile int scanGuard;
+
+ private static final int SG_UNIT = 1 << 16;
/**
- * Forces decrement of encoded workerCounts, awaiting nonzero if
- * (rarely) necessary when other count updates lag.
+ * The wakeup interval (in nanoseconds) for a worker waiting for a
+ * task when the pool is quiescent to instead try to shrink the
+ * number of workers. The exact value does not matter too
+ * much. It must be short enough to release resources during
+ * sustained periods of idleness, but not so short that threads
+ * are continually re-created.
+ */
+ private static final long SHRINK_RATE =
+ 4L * 1000L * 1000L * 1000L; // 4 seconds
+
+ /**
+ * Top-level loop for worker threads: On each step: if the
+ * previous step swept through all queues and found no tasks, or
+ * there are excess threads, then possibly blocks. Otherwise,
+ * scans for and, if found, executes a task. Returns when pool
+ * and/or worker terminate.
*
- * @param dr -- either zero or ONE_RUNNING
- * @param dt -- either zero or ONE_TOTAL
+ * @param w the worker
*/
- private void decrementWorkerCounts(int dr, int dt) {
- for (;;) {
- int wc = workerCounts;
- if ((wc & RUNNING_COUNT_MASK) - dr < 0 ||
- (wc >>> TOTAL_COUNT_SHIFT) - dt < 0) {
- if ((runState & TERMINATED) != 0)
- return; // lagging termination on a backout
- Thread.yield();
+ final void work(ForkJoinWorkerThread w) {
+ boolean swept = false; // true on empty scans
+ long c;
+ while (!w.terminate && (int)(c = ctl) >= 0) {
+ int a; // active count
+ if (!swept && (a = (int)(c >> AC_SHIFT)) <= 0)
+ swept = scan(w, a);
+ else if (tryAwaitWork(w, c))
+ swept = false;
+ }
+ }
+
+ // Signalling
+
+ /**
+ * Wakes up or creates a worker.
+ */
+ final void signalWork() {
+ /*
+ * The while condition is true if: (there is are too few total
+ * workers OR there is at least one waiter) AND (there are too
+ * few active workers OR the pool is terminating). The value
+ * of e distinguishes the remaining cases: zero (no waiters)
+ * for create, negative if terminating (in which case do
+ * nothing), else release a waiter. The secondary checks for
+ * release (non-null array etc) can fail if the pool begins
+ * terminating after the test, and don't impose any added cost
+ * because JVMs must perform null and bounds checks anyway.
+ */
+ long c; int e, u;
+ while ((((e = (int)(c = ctl)) | (u = (int)(c >>> 32))) &
+ (INT_SIGN|SHORT_SIGN)) == (INT_SIGN|SHORT_SIGN) && e >= 0) {
+ if (e > 0) { // release a waiting worker
+ int i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
+ if ((ws = workers) == null ||
+ (i = ~e & SMASK) >= ws.length ||
+ (w = ws[i]) == null)
+ break;
+ long nc = (((long)(w.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT) << 32));
+ if (w.eventCount == e &&
+ UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
+ w.eventCount = (e + EC_UNIT) & E_MASK;
+ if (w.parked)
+ UNSAFE.unpark(w);
+ break;
+ }
+ }
+ else if (UNSAFE.compareAndSwapLong
+ (this, ctlOffset, c,
+ (long)(((u + UTC_UNIT) & UTC_MASK) |
+ ((u + UAC_UNIT) & UAC_MASK)) << 32)) {
+ addWorker();
+ break;
}
- if (UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - (dr + dt)))
- return;
}
}
/**
- * Tries decrementing active count; fails on contention.
- * Called when workers cannot find tasks to run.
+ * Variant of signalWork to help release waiters on rescans.
+ * Tries once to release a waiter if active count < 0.
+ *
+ * @return false if failed due to contention, else true
*/
- final boolean tryDecrementActiveCount() {
- int c;
- return UNSAFE.compareAndSwapInt(this, runStateOffset,
- c = runState, c - 1);
- }
-
- /**
- * Advances to at least the given level. Returns true if not
- * already in at least the given level.
- */
- private boolean advanceRunLevel(int level) {
- for (;;) {
- int s = runState;
- if ((s & level) != 0)
+ private boolean tryReleaseWaiter() {
+ long c; int e, i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
+ if ((e = (int)(c = ctl)) > 0 &&
+ (int)(c >> AC_SHIFT) < 0 &&
+ (ws = workers) != null &&
+ (i = ~e & SMASK) < ws.length &&
+ (w = ws[i]) != null) {
+ long nc = ((long)(w.nextWait & E_MASK) |
+ ((c + AC_UNIT) & (AC_MASK|TC_MASK)));
+ if (w.eventCount != e ||
+ !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
return false;
- if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, s | level))
- return true;
+ w.eventCount = (e + EC_UNIT) & E_MASK;
+ if (w.parked)
+ UNSAFE.unpark(w);
}
+ return true;
}
- // workers array maintenance
+ // Scanning for tasks
/**
- * Records and returns a workers array index for new worker.
+ * Scans for and, if found, executes one task. Scans start at a
+ * random index of workers array, and randomly select the first
+ * (2*#workers)-1 probes, and then, if all empty, resort to 2
+ * circular sweeps, which is necessary to check quiescence. and
+ * taking a submission only if no stealable tasks were found. The
+ * steal code inside the loop is a specialized form of
+ * ForkJoinWorkerThread.deqTask, followed bookkeeping to support
+ * helpJoinTask and signal propagation. The code for submission
+ * queues is almost identical. On each steal, the worker completes
+ * not only the task, but also all local tasks that this task may
+ * have generated. On detecting staleness or contention when
+ * trying to take a task, this method returns without finishing
+ * sweep, which allows global state rechecks before retry.
+ *
+ * @param w the worker
+ * @param a the number of active workers
+ * @return true if swept all queues without finding a task
*/
- private int recordWorker(ForkJoinWorkerThread w) {
- // Try using slot totalCount-1. If not available, scan and/or resize
- int k = (workerCounts >>> TOTAL_COUNT_SHIFT) - 1;
- final ReentrantLock lock = this.workerLock;
- lock.lock();
- try {
- ForkJoinWorkerThread[] ws = workers;
- int n = ws.length;
- if (k < 0 || k >= n || ws[k] != null) {
- for (k = 0; k < n && ws[k] != null; ++k)
- ;
- if (k == n)
- ws = workers = Arrays.copyOf(ws, n << 1);
+ private boolean scan(ForkJoinWorkerThread w, int a) {
+ int g = scanGuard; // mask 0 avoids useless scans if only one active
+ int m = (parallelism == 1 - a && blockedCount == 0) ? 0 : g & SMASK;
+ ForkJoinWorkerThread[] ws = workers;
+ if (ws == null || ws.length <= m) // staleness check
+ return false;
+ for (int r = w.seed, k = r, j = -(m + m); j <= m + m; ++j) {
+ ForkJoinTask> t; ForkJoinTask>[] q; int b, i;
+ ForkJoinWorkerThread v = ws[k & m];
+ if (v != null && (b = v.queueBase) != v.queueTop &&
+ (q = v.queue) != null && (i = (q.length - 1) & b) >= 0) {
+ long u = (i << ASHIFT) + ABASE;
+ if ((t = q[i]) != null && v.queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ int d = (v.queueBase = b + 1) - v.queueTop;
+ v.stealHint = w.poolIndex;
+ if (d != 0)
+ signalWork(); // propagate if nonempty
+ w.execTask(t);
+ }
+ r ^= r << 13; r ^= r >>> 17; w.seed = r ^ (r << 5);
+ return false; // store next seed
}
- ws[k] = w;
- int c = eventCount; // advance event count to ensure visibility
- UNSAFE.compareAndSwapInt(this, eventCountOffset, c, c+1);
- } finally {
- lock.unlock();
+ else if (j < 0) { // xorshift
+ r ^= r << 13; r ^= r >>> 17; k = r ^= r << 5;
+ }
+ else
+ ++k;
+ }
+ if (scanGuard != g) // staleness check
+ return false;
+ else { // try to take submission
+ ForkJoinTask> t; ForkJoinTask>[] q; int b, i;
+ if ((b = queueBase) != queueTop &&
+ (q = submissionQueue) != null &&
+ (i = (q.length - 1) & b) >= 0) {
+ long u = (i << ASHIFT) + ABASE;
+ if ((t = q[i]) != null && queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ queueBase = b + 1;
+ w.execTask(t);
+ }
+ return false;
+ }
+ return true; // all queues empty
}
- return k;
}
/**
- * Nulls out record of worker in workers array.
+ * Tries to enqueue worker w in wait queue and await change in
+ * worker's eventCount. If the pool is quiescent, possibly
+ * terminates worker upon exit. Otherwise, before blocking,
+ * rescans queues to avoid missed signals. Upon finding work,
+ * releases at least one worker (which may be the current
+ * worker). Rescans restart upon detected staleness or failure to
+ * release due to contention. Note the unusual conventions about
+ * Thread.interrupt here and elsewhere: Because interrupts are
+ * used solely to alert threads to check termination, which is
+ * checked here anyway, we clear status (using Thread.interrupted)
+ * before any call to park, so that park does not immediately
+ * return due to status being set via some other unrelated call to
+ * interrupt in user code.
+ *
+ * @param w the calling worker
+ * @param c the ctl value on entry
+ * @return true if waited or another thread was released upon enq
*/
- private void forgetWorker(ForkJoinWorkerThread w) {
- int idx = w.poolIndex;
- // Locking helps method recordWorker avoid unnecessary expansion
- final ReentrantLock lock = this.workerLock;
+ private boolean tryAwaitWork(ForkJoinWorkerThread w, long c) {
+ int v = w.eventCount;
+ w.nextWait = (int)c; // w's successor record
+ long nc = (long)(v & E_MASK) | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
+ if (ctl != c || !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
+ long d = ctl; // return true if lost to a deq, to force scan
+ return (int)d != (int)c && ((d - c) & AC_MASK) >= 0L;
+ }
+ for (int sc = w.stealCount; sc != 0;) { // accumulate stealCount
+ long s = stealCount;
+ if (UNSAFE.compareAndSwapLong(this, stealCountOffset, s, s + sc))
+ sc = w.stealCount = 0;
+ else if (w.eventCount != v)
+ return true; // update next time
+ }
+ if (parallelism + (int)(nc >> AC_SHIFT) == 0 &&
+ blockedCount == 0 && quiescerCount == 0)
+ idleAwaitWork(w, nc, c, v); // quiescent
+ for (boolean rescanned = false;;) {
+ if (w.eventCount != v)
+ return true;
+ if (!rescanned) {
+ int g = scanGuard, m = g & SMASK;
+ ForkJoinWorkerThread[] ws = workers;
+ if (ws != null && m < ws.length) {
+ rescanned = true;
+ for (int i = 0; i <= m; ++i) {
+ ForkJoinWorkerThread u = ws[i];
+ if (u != null) {
+ if (u.queueBase != u.queueTop &&
+ !tryReleaseWaiter())
+ rescanned = false; // contended
+ if (w.eventCount != v)
+ return true;
+ }
+ }
+ }
+ if (scanGuard != g || // stale
+ (queueBase != queueTop && !tryReleaseWaiter()))
+ rescanned = false;
+ if (!rescanned)
+ Thread.yield(); // reduce contention
+ else
+ Thread.interrupted(); // clear before park
+ }
+ else {
+ w.parked = true; // must recheck
+ if (w.eventCount != v) {
+ w.parked = false;
+ return true;
+ }
+ LockSupport.park(this);
+ rescanned = w.parked = false;
+ }
+ }
+ }
+
+ /**
+ * If inactivating worker w has caused pool to become
+ * quiescent, check for pool termination, and wait for event
+ * for up to SHRINK_RATE nanosecs (rescans are unnecessary in
+ * this case because quiescence reflects consensus about lack
+ * of work). On timeout, if ctl has not changed, terminate the
+ * worker. Upon its termination (see deregisterWorker), it may
+ * wake up another worker to possibly repeat this process.
+ *
+ * @param w the calling worker
+ * @param currentCtl the ctl value after enqueuing w
+ * @param prevCtl the ctl value if w terminated
+ * @param v the eventCount w awaits change
+ */
+ private void idleAwaitWork(ForkJoinWorkerThread w, long currentCtl,
+ long prevCtl, int v) {
+ if (w.eventCount == v) {
+ if (shutdown)
+ tryTerminate(false);
+ ForkJoinTask.helpExpungeStaleExceptions(); // help clean weak refs
+ while (ctl == currentCtl) {
+ long startTime = System.nanoTime();
+ w.parked = true;
+ if (w.eventCount == v) // must recheck
+ LockSupport.parkNanos(this, SHRINK_RATE);
+ w.parked = false;
+ if (w.eventCount != v)
+ break;
+ else if (System.nanoTime() - startTime < SHRINK_RATE)
+ Thread.interrupted(); // spurious wakeup
+ else if (UNSAFE.compareAndSwapLong(this, ctlOffset,
+ currentCtl, prevCtl)) {
+ w.terminate = true; // restore previous
+ w.eventCount = ((int)currentCtl + EC_UNIT) & E_MASK;
+ break;
+ }
+ }
+ }
+ }
+
+ // Submissions
+
+ /**
+ * Enqueues the given task in the submissionQueue. Same idea as
+ * ForkJoinWorkerThread.pushTask except for use of submissionLock.
+ *
+ * @param t the task
+ */
+ private void addSubmission(ForkJoinTask> t) {
+ final ReentrantLock lock = this.submissionLock;
lock.lock();
try {
- ForkJoinWorkerThread[] ws = workers;
- if (idx >= 0 && idx < ws.length && ws[idx] == w) // verify
- ws[idx] = null;
+ ForkJoinTask>[] q; int s, m;
+ if ((q = submissionQueue) != null) { // ignore if queue removed
+ long u = (((s = queueTop) & (m = q.length-1)) << ASHIFT)+ABASE;
+ UNSAFE.putOrderedObject(q, u, t);
+ queueTop = s + 1;
+ if (s - queueBase == m)
+ growSubmissionQueue();
+ }
} finally {
lock.unlock();
}
+ signalWork();
+ }
+
+ // (pollSubmission is defined below with exported methods)
+
+ /**
+ * Creates or doubles submissionQueue array.
+ * Basically identical to ForkJoinWorkerThread version.
+ */
+ private void growSubmissionQueue() {
+ ForkJoinTask>[] oldQ = submissionQueue;
+ int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
+ if (size > MAXIMUM_QUEUE_CAPACITY)
+ throw new RejectedExecutionException("Queue capacity exceeded");
+ if (size < INITIAL_QUEUE_CAPACITY)
+ size = INITIAL_QUEUE_CAPACITY;
+ ForkJoinTask>[] q = submissionQueue = new ForkJoinTask>[size];
+ int mask = size - 1;
+ int top = queueTop;
+ int oldMask;
+ if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
+ for (int b = queueBase; b != top; ++b) {
+ long u = ((b & oldMask) << ASHIFT) + ABASE;
+ Object x = UNSAFE.getObjectVolatile(oldQ, u);
+ if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
+ UNSAFE.putObjectVolatile
+ (q, ((b & mask) << ASHIFT) + ABASE, x);
+ }
+ }
+ }
+
+ // Blocking support
+
+ /**
+ * Tries to increment blockedCount, decrement active count
+ * (sometimes implicitly) and possibly release or create a
+ * compensating worker in preparation for blocking. Fails
+ * on contention or termination.
+ *
+ * @return true if the caller can block, else should recheck and retry
+ */
+ private boolean tryPreBlock() {
+ int b = blockedCount;
+ if (UNSAFE.compareAndSwapInt(this, blockedCountOffset, b, b + 1)) {
+ int pc = parallelism;
+ do {
+ ForkJoinWorkerThread[] ws; ForkJoinWorkerThread w;
+ int e, ac, tc, rc, i;
+ long c = ctl;
+ int u = (int)(c >>> 32);
+ if ((e = (int)c) < 0) {
+ // skip -- terminating
+ }
+ else if ((ac = (u >> UAC_SHIFT)) <= 0 && e != 0 &&
+ (ws = workers) != null &&
+ (i = ~e & SMASK) < ws.length &&
+ (w = ws[i]) != null) {
+ long nc = ((long)(w.nextWait & E_MASK) |
+ (c & (AC_MASK|TC_MASK)));
+ if (w.eventCount == e &&
+ UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
+ w.eventCount = (e + EC_UNIT) & E_MASK;
+ if (w.parked)
+ UNSAFE.unpark(w);
+ return true; // release an idle worker
+ }
+ }
+ else if ((tc = (short)(u >>> UTC_SHIFT)) >= 0 && ac + pc > 1) {
+ long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
+ if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
+ return true; // no compensation needed
+ }
+ else if (tc + pc < MAX_ID) {
+ long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
+ if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
+ addWorker();
+ return true; // create a replacement
+ }
+ }
+ // try to back out on any failure and let caller retry
+ } while (!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
+ b = blockedCount, b - 1));
+ }
+ return false;
+ }
+
+ /**
+ * Decrements blockedCount and increments active count
+ */
+ private void postBlock() {
+ long c;
+ do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset, // no mask
+ c = ctl, c + AC_UNIT));
+ int b;
+ do {} while(!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
+ b = blockedCount, b - 1));
+ }
+
+ /**
+ * Possibly blocks waiting for the given task to complete, or
+ * cancels the task if terminating. Fails to wait if contended.
+ *
+ * @param joinMe the task
+ */
+ final void tryAwaitJoin(ForkJoinTask> joinMe) {
+ int s;
+ Thread.interrupted(); // clear interrupts before checking termination
+ if (joinMe.status >= 0) {
+ if (tryPreBlock()) {
+ joinMe.tryAwaitDone(0L);
+ postBlock();
+ }
+ else if ((ctl & STOP_BIT) != 0L)
+ joinMe.cancelIgnoringExceptions();
+ }
+ }
+
+ /**
+ * Possibly blocks the given worker waiting for joinMe to
+ * complete or timeout
+ *
+ * @param joinMe the task
+ * @param millis the wait time for underlying Object.wait
+ */
+ final void timedAwaitJoin(ForkJoinTask> joinMe, long nanos) {
+ while (joinMe.status >= 0) {
+ Thread.interrupted();
+ if ((ctl & STOP_BIT) != 0L) {
+ joinMe.cancelIgnoringExceptions();
+ break;
+ }
+ if (tryPreBlock()) {
+ long last = System.nanoTime();
+ while (joinMe.status >= 0) {
+ long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+ if (millis <= 0)
+ break;
+ joinMe.tryAwaitDone(millis);
+ if (joinMe.status < 0)
+ break;
+ if ((ctl & STOP_BIT) != 0L) {
+ joinMe.cancelIgnoringExceptions();
+ break;
+ }
+ long now = System.nanoTime();
+ nanos -= now - last;
+ last = now;
+ }
+ postBlock();
+ break;
+ }
+ }
+ }
+
+ /**
+ * If necessary, compensates for blocker, and blocks
+ */
+ private void awaitBlocker(ManagedBlocker blocker)
+ throws InterruptedException {
+ while (!blocker.isReleasable()) {
+ if (tryPreBlock()) {
+ try {
+ do {} while (!blocker.isReleasable() && !blocker.block());
+ } finally {
+ postBlock();
+ }
+ break;
+ }
+ }
+ }
+
+ // Creating, registering and deregistring workers
+
+ /**
+ * Tries to create and start a worker; minimally rolls back counts
+ * on failure.
+ */
+ private void addWorker() {
+ Throwable ex = null;
+ ForkJoinWorkerThread t = null;
+ try {
+ t = factory.newThread(this);
+ } catch (Throwable e) {
+ ex = e;
+ }
+ if (t == null) { // null or exceptional factory return
+ long c; // adjust counts
+ do {} while (!UNSAFE.compareAndSwapLong
+ (this, ctlOffset, c = ctl,
+ (((c - AC_UNIT) & AC_MASK) |
+ ((c - TC_UNIT) & TC_MASK) |
+ (c & ~(AC_MASK|TC_MASK)))));
+ // Propagate exception if originating from an external caller
+ if (!tryTerminate(false) && ex != null &&
+ !(Thread.currentThread() instanceof ForkJoinWorkerThread))
+ UNSAFE.throwException(ex);
+ }
+ else
+ t.start();
+ }
+
+ /**
+ * Callback from ForkJoinWorkerThread constructor to assign a
+ * public name
+ */
+ final String nextWorkerName() {
+ for (int n;;) {
+ if (UNSAFE.compareAndSwapInt(this, nextWorkerNumberOffset,
+ n = nextWorkerNumber, ++n))
+ return workerNamePrefix + n;
+ }
+ }
+
+ /**
+ * Callback from ForkJoinWorkerThread constructor to
+ * determine its poolIndex and record in workers array.
+ *
+ * @param w the worker
+ * @return the worker's pool index
+ */
+ final int registerWorker(ForkJoinWorkerThread w) {
+ /*
+ * In the typical case, a new worker acquires the lock, uses
+ * next available index and returns quickly. Since we should
+ * not block callers (ultimately from signalWork or
+ * tryPreBlock) waiting for the lock needed to do this, we
+ * instead help release other workers while waiting for the
+ * lock.
+ */
+ for (int g;;) {
+ ForkJoinWorkerThread[] ws;
+ if (((g = scanGuard) & SG_UNIT) == 0 &&
+ UNSAFE.compareAndSwapInt(this, scanGuardOffset,
+ g, g | SG_UNIT)) {
+ int k = nextWorkerIndex;
+ try {
+ if ((ws = workers) != null) { // ignore on shutdown
+ int n = ws.length;
+ if (k < 0 || k >= n || ws[k] != null) {
+ for (k = 0; k < n && ws[k] != null; ++k)
+ ;
+ if (k == n)
+ ws = workers = Arrays.copyOf(ws, n << 1);
+ }
+ ws[k] = w;
+ nextWorkerIndex = k + 1;
+ int m = g & SMASK;
+ g = k >= m? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1);
+ }
+ } finally {
+ scanGuard = g;
+ }
+ return k;
+ }
+ else if ((ws = workers) != null) { // help release others
+ for (ForkJoinWorkerThread u : ws) {
+ if (u != null && u.queueBase != u.queueTop) {
+ if (tryReleaseWaiter())
+ break;
+ }
+ }
+ }
+ }
}
/**
@@ -743,415 +1200,46 @@ public class ForkJoinPool extends AbstractExecutorService {
*
* @param w the worker
*/
- final void workerTerminated(ForkJoinWorkerThread w) {
- forgetWorker(w);
- decrementWorkerCounts(w.isTrimmed() ? 0 : ONE_RUNNING, ONE_TOTAL);
- while (w.stealCount != 0) // collect final count
- tryAccumulateStealCount(w);
- tryTerminate(false);
- }
-
- // Waiting for and signalling events
-
- /**
- * Releases workers blocked on a count not equal to current count.
- * Normally called after precheck that eventWaiters isn't zero to
- * avoid wasted array checks. Gives up upon a change in count or
- * upon releasing four workers, letting others take over.
- */
- private void releaseEventWaiters() {
- ForkJoinWorkerThread[] ws = workers;
- int n = ws.length;
- long h = eventWaiters;
- int ec = eventCount;
- int releases = 4;
- ForkJoinWorkerThread w; int id;
- while ((id = (((int)h) & WAITER_ID_MASK) - 1) >= 0 &&
- (int)(h >>> EVENT_COUNT_SHIFT) != ec &&
- id < n && (w = ws[id]) != null) {
- if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
- h, w.nextWaiter)) {
- LockSupport.unpark(w);
- if (--releases == 0)
- break;
+ final void deregisterWorker(ForkJoinWorkerThread w, Throwable ex) {
+ int idx = w.poolIndex;
+ int sc = w.stealCount;
+ int steps = 0;
+ // Remove from array, adjust worker counts and collect steal count.
+ // We can intermix failed removes or adjusts with steal updates
+ do {
+ long s, c;
+ int g;
+ if (steps == 0 && ((g = scanGuard) & SG_UNIT) == 0 &&
+ UNSAFE.compareAndSwapInt(this, scanGuardOffset,
+ g, g |= SG_UNIT)) {
+ ForkJoinWorkerThread[] ws = workers;
+ if (ws != null && idx >= 0 &&
+ idx < ws.length && ws[idx] == w)
+ ws[idx] = null; // verify
+ nextWorkerIndex = idx;
+ scanGuard = g + SG_UNIT;
+ steps = 1;
}
- if (eventCount != ec)
- break;
- h = eventWaiters;
+ if (steps == 1 &&
+ UNSAFE.compareAndSwapLong(this, ctlOffset, c = ctl,
+ (((c - AC_UNIT) & AC_MASK) |
+ ((c - TC_UNIT) & TC_MASK) |
+ (c & ~(AC_MASK|TC_MASK)))))
+ steps = 2;
+ if (sc != 0 &&
+ UNSAFE.compareAndSwapLong(this, stealCountOffset,
+ s = stealCount, s + sc))
+ sc = 0;
+ } while (steps != 2 || sc != 0);
+ if (!tryTerminate(false)) {
+ if (ex != null) // possibly replace if died abnormally
+ signalWork();
+ else
+ tryReleaseWaiter();
}
}
- /**
- * Tries to advance eventCount and releases waiters. Called only
- * from workers.
- */
- final void signalWork() {
- int c; // try to increment event count -- CAS failure OK
- UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
- if (eventWaiters != 0L)
- releaseEventWaiters();
- }
-
- /**
- * Adds the given worker to event queue and blocks until
- * terminating or event count advances from the given value
- *
- * @param w the calling worker thread
- * @param ec the count
- */
- private void eventSync(ForkJoinWorkerThread w, int ec) {
- long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1));
- long h;
- while ((runState < SHUTDOWN || !tryTerminate(false)) &&
- (((int)(h = eventWaiters) & WAITER_ID_MASK) == 0 ||
- (int)(h >>> EVENT_COUNT_SHIFT) == ec) &&
- eventCount == ec) {
- if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
- w.nextWaiter = h, nh)) {
- awaitEvent(w, ec);
- break;
- }
- }
- }
-
- /**
- * Blocks the given worker (that has already been entered as an
- * event waiter) until terminating or event count advances from
- * the given value. The oldest (first) waiter uses a timed wait to
- * occasionally one-by-one shrink the number of workers (to a
- * minimum of one) if the pool has not been used for extended
- * periods.
- *
- * @param w the calling worker thread
- * @param ec the count
- */
- private void awaitEvent(ForkJoinWorkerThread w, int ec) {
- while (eventCount == ec) {
- if (tryAccumulateStealCount(w)) { // transfer while idle
- boolean untimed = (w.nextWaiter != 0L ||
- (workerCounts & RUNNING_COUNT_MASK) <= 1);
- long startTime = untimed ? 0 : System.nanoTime();
- Thread.interrupted(); // clear/ignore interrupt
- if (w.isTerminating() || eventCount != ec)
- break; // recheck after clear
- if (untimed)
- LockSupport.park(w);
- else {
- LockSupport.parkNanos(w, SHRINK_RATE_NANOS);
- if (eventCount != ec || w.isTerminating())
- break;
- if (System.nanoTime() - startTime >= SHRINK_RATE_NANOS)
- tryShutdownUnusedWorker(ec);
- }
- }
- }
- }
-
- // Maintaining parallelism
-
- /**
- * Pushes worker onto the spare stack.
- */
- final void pushSpare(ForkJoinWorkerThread w) {
- int ns = (++w.spareCount << SPARE_COUNT_SHIFT) | (w.poolIndex + 1);
- do {} while (!UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
- w.nextSpare = spareWaiters,ns));
- }
-
- /**
- * Tries (once) to resume a spare if the number of running
- * threads is less than target.
- */
- private void tryResumeSpare() {
- int sw, id;
- ForkJoinWorkerThread[] ws = workers;
- int n = ws.length;
- ForkJoinWorkerThread w;
- if ((sw = spareWaiters) != 0 &&
- (id = (sw & SPARE_ID_MASK) - 1) >= 0 &&
- id < n && (w = ws[id]) != null &&
- (runState >= TERMINATING ||
- (workerCounts & RUNNING_COUNT_MASK) < parallelism) &&
- spareWaiters == sw &&
- UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
- sw, w.nextSpare)) {
- int c; // increment running count before resume
- do {} while (!UNSAFE.compareAndSwapInt
- (this, workerCountsOffset,
- c = workerCounts, c + ONE_RUNNING));
- if (w.tryUnsuspend())
- LockSupport.unpark(w);
- else // back out if w was shutdown
- decrementWorkerCounts(ONE_RUNNING, 0);
- }
- }
-
- /**
- * Tries to increase the number of running workers if below target
- * parallelism: If a spare exists tries to resume it via
- * tryResumeSpare. Otherwise, if not enough total workers or all
- * existing workers are busy, adds a new worker. In all cases also
- * helps wake up releasable workers waiting for work.
- */
- private void helpMaintainParallelism() {
- int pc = parallelism;
- int wc, rs, tc;
- while (((wc = workerCounts) & RUNNING_COUNT_MASK) < pc &&
- (rs = runState) < TERMINATING) {
- if (spareWaiters != 0)
- tryResumeSpare();
- else if ((tc = wc >>> TOTAL_COUNT_SHIFT) >= MAX_WORKERS ||
- (tc >= pc && (rs & ACTIVE_COUNT_MASK) != tc))
- break; // enough total
- else if (runState == rs && workerCounts == wc &&
- UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc,
- wc + (ONE_RUNNING|ONE_TOTAL))) {
- ForkJoinWorkerThread w = null;
- Throwable fail = null;
- try {
- w = factory.newThread(this);
- } catch (Throwable ex) {
- fail = ex;
- }
- if (w == null) { // null or exceptional factory return
- decrementWorkerCounts(ONE_RUNNING, ONE_TOTAL);
- tryTerminate(false); // handle failure during shutdown
- // If originating from an external caller,
- // propagate exception, else ignore
- if (fail != null && runState < TERMINATING &&
- !(Thread.currentThread() instanceof
- ForkJoinWorkerThread))
- UNSAFE.throwException(fail);
- break;
- }
- w.start(recordWorker(w), ueh);
- if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc)
- break; // add at most one unless total below target
- }
- }
- if (eventWaiters != 0L)
- releaseEventWaiters();
- }
-
- /**
- * Callback from the oldest waiter in awaitEvent waking up after a
- * period of non-use. If all workers are idle, tries (once) to
- * shutdown an event waiter or a spare, if one exists. Note that
- * we don't need CAS or locks here because the method is called
- * only from one thread occasionally waking (and even misfires are
- * OK). Note that until the shutdown worker fully terminates,
- * workerCounts will overestimate total count, which is tolerable.
- *
- * @param ec the event count waited on by caller (to abort
- * attempt if count has since changed).
- */
- private void tryShutdownUnusedWorker(int ec) {
- if (runState == 0 && eventCount == ec) { // only trigger if all idle
- ForkJoinWorkerThread[] ws = workers;
- int n = ws.length;
- ForkJoinWorkerThread w = null;
- boolean shutdown = false;
- int sw;
- long h;
- if ((sw = spareWaiters) != 0) { // prefer killing spares
- int id = (sw & SPARE_ID_MASK) - 1;
- if (id >= 0 && id < n && (w = ws[id]) != null &&
- UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
- sw, w.nextSpare))
- shutdown = true;
- }
- else if ((h = eventWaiters) != 0L) {
- long nh;
- int id = (((int)h) & WAITER_ID_MASK) - 1;
- if (id >= 0 && id < n && (w = ws[id]) != null &&
- (nh = w.nextWaiter) != 0L && // keep at least one worker
- UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh))
- shutdown = true;
- }
- if (w != null && shutdown) {
- w.shutdown();
- LockSupport.unpark(w);
- }
- }
- releaseEventWaiters(); // in case of interference
- }
-
- /**
- * Callback from workers invoked upon each top-level action (i.e.,
- * stealing a task or taking a submission and running it).
- * Performs one or more of the following:
- *
- * 1. If the worker is active and either did not run a task
- * or there are too many workers, try to set its active status
- * to inactive and update activeCount. On contention, we may
- * try again in this or a subsequent call.
- *
- * 2. If not enough total workers, help create some.
- *
- * 3. If there are too many running workers, suspend this worker
- * (first forcing inactive if necessary). If it is not needed,
- * it may be shutdown while suspended (via
- * tryShutdownUnusedWorker). Otherwise, upon resume it
- * rechecks running thread count and need for event sync.
- *
- * 4. If worker did not run a task, await the next task event via
- * eventSync if necessary (first forcing inactivation), upon
- * which the worker may be shutdown via
- * tryShutdownUnusedWorker. Otherwise, help release any
- * existing event waiters that are now releasable,
- *
- * @param w the worker
- * @param ran true if worker ran a task since last call to this method
- */
- final void preStep(ForkJoinWorkerThread w, boolean ran) {
- int wec = w.lastEventCount;
- boolean active = w.active;
- boolean inactivate = false;
- int pc = parallelism;
- while (w.runState == 0) {
- int rs = runState;
- if (rs >= TERMINATING) { // propagate shutdown
- w.shutdown();
- break;
- }
- if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) &&
- UNSAFE.compareAndSwapInt(this, runStateOffset, rs, --rs)) {
- inactivate = active = w.active = false;
- if (rs == SHUTDOWN) { // all inactive and shut down
- tryTerminate(false);
- continue;
- }
- }
- int wc = workerCounts; // try to suspend as spare
- if ((wc & RUNNING_COUNT_MASK) > pc) {
- if (!(inactivate |= active) && // must inactivate to suspend
- workerCounts == wc &&
- UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING))
- w.suspendAsSpare();
- }
- else if ((wc >>> TOTAL_COUNT_SHIFT) < pc)
- helpMaintainParallelism(); // not enough workers
- else if (ran)
- break;
- else {
- long h = eventWaiters;
- int ec = eventCount;
- if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec)
- releaseEventWaiters(); // release others before waiting
- else if (ec != wec) {
- w.lastEventCount = ec; // no need to wait
- break;
- }
- else if (!(inactivate |= active))
- eventSync(w, wec); // must inactivate before sync
- }
- }
- }
-
- /**
- * Helps and/or blocks awaiting join of the given task.
- * See above for explanation.
- *
- * @param joinMe the task to join
- * @param worker the current worker thread
- * @param timed true if wait should time out
- * @param nanos timeout value if timed
- */
- final void awaitJoin(ForkJoinTask> joinMe, ForkJoinWorkerThread worker,
- boolean timed, long nanos) {
- long startTime = timed ? System.nanoTime() : 0L;
- int retries = 2 + (parallelism >> 2); // #helpJoins before blocking
- boolean running = true; // false when count decremented
- while (joinMe.status >= 0) {
- if (runState >= TERMINATING) {
- joinMe.cancelIgnoringExceptions();
- break;
- }
- running = worker.helpJoinTask(joinMe, running);
- if (joinMe.status < 0)
- break;
- if (retries > 0) {
- --retries;
- continue;
- }
- int wc = workerCounts;
- if ((wc & RUNNING_COUNT_MASK) != 0) {
- if (running) {
- if (!UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING))
- continue;
- running = false;
- }
- long h = eventWaiters;
- if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
- releaseEventWaiters();
- if ((workerCounts & RUNNING_COUNT_MASK) != 0) {
- long ms; int ns;
- if (!timed) {
- ms = JOIN_TIMEOUT_MILLIS;
- ns = 0;
- }
- else { // at most JOIN_TIMEOUT_MILLIS per wait
- long nt = nanos - (System.nanoTime() - startTime);
- if (nt <= 0L)
- break;
- ms = nt / 1000000;
- if (ms > JOIN_TIMEOUT_MILLIS) {
- ms = JOIN_TIMEOUT_MILLIS;
- ns = 0;
- }
- else
- ns = (int) (nt % 1000000);
- }
- joinMe.internalAwaitDone(ms, ns);
- }
- if (joinMe.status < 0)
- break;
- }
- helpMaintainParallelism();
- }
- if (!running) {
- int c;
- do {} while (!UNSAFE.compareAndSwapInt
- (this, workerCountsOffset,
- c = workerCounts, c + ONE_RUNNING));
- }
- }
-
- /**
- * Same idea as awaitJoin, but no helping, retries, or timeouts.
- */
- final void awaitBlocker(ManagedBlocker blocker)
- throws InterruptedException {
- while (!blocker.isReleasable()) {
- int wc = workerCounts;
- if ((wc & RUNNING_COUNT_MASK) == 0)
- helpMaintainParallelism();
- else if (UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING)) {
- try {
- while (!blocker.isReleasable()) {
- long h = eventWaiters;
- if (h != 0L &&
- (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
- releaseEventWaiters();
- else if ((workerCounts & RUNNING_COUNT_MASK) == 0 &&
- runState < TERMINATING)
- helpMaintainParallelism();
- else if (blocker.block())
- break;
- }
- } finally {
- int c;
- do {} while (!UNSAFE.compareAndSwapInt
- (this, workerCountsOffset,
- c = workerCounts, c + ONE_RUNNING));
- }
- break;
- }
- }
- }
+ // Shutdown and termination
/**
* Possibly initiates and/or completes termination.
@@ -1161,97 +1249,132 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return true if now terminating or terminated
*/
private boolean tryTerminate(boolean now) {
- if (now)
- advanceRunLevel(SHUTDOWN); // ensure at least SHUTDOWN
- else if (runState < SHUTDOWN ||
- !submissionQueue.isEmpty() ||
- (runState & ACTIVE_COUNT_MASK) != 0)
- return false;
-
- if (advanceRunLevel(TERMINATING))
- startTerminating();
-
- // Finish now if all threads terminated; else in some subsequent call
- if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) {
- advanceRunLevel(TERMINATED);
- termination.forceTermination();
+ long c;
+ while (((c = ctl) & STOP_BIT) == 0) {
+ if (!now) {
+ if ((int)(c >> AC_SHIFT) != -parallelism)
+ return false;
+ if (!shutdown || blockedCount != 0 || quiescerCount != 0 ||
+ queueBase != queueTop) {
+ if (ctl == c) // staleness check
+ return false;
+ continue;
+ }
+ }
+ if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, c | STOP_BIT))
+ startTerminating();
+ }
+ if ((short)(c >>> TC_SHIFT) == -parallelism) { // signal when 0 workers
+ final ReentrantLock lock = this.submissionLock;
+ lock.lock();
+ try {
+ termination.signalAll();
+ } finally {
+ lock.unlock();
+ }
}
return true;
}
/**
- * Actions on transition to TERMINATING
- *
- * Runs up to four passes through workers: (0) shutting down each
- * (without waking up if parked) to quickly spread notifications
- * without unnecessary bouncing around event queues etc (1) wake
- * up and help cancel tasks (2) interrupt (3) mop up races with
- * interrupted workers
+ * Runs up to three passes through workers: (0) Setting
+ * termination status for each worker, followed by wakeups up to
+ * queued workers; (1) helping cancel tasks; (2) interrupting
+ * lagging threads (likely in external tasks, but possibly also
+ * blocked in joins). Each pass repeats previous steps because of
+ * potential lagging thread creation.
*/
private void startTerminating() {
cancelSubmissions();
- for (int passes = 0; passes < 4 && workerCounts != 0; ++passes) {
- int c; // advance event count
- UNSAFE.compareAndSwapInt(this, eventCountOffset,
- c = eventCount, c+1);
- eventWaiters = 0L; // clobber lists
- spareWaiters = 0;
- for (ForkJoinWorkerThread w : workers) {
- if (w != null) {
- w.shutdown();
- if (passes > 0 && !w.isTerminated()) {
- w.cancelTasks();
- LockSupport.unpark(w);
- if (passes > 1 && !w.isInterrupted()) {
- try {
- w.interrupt();
- } catch (SecurityException ignore) {
+ for (int pass = 0; pass < 3; ++pass) {
+ ForkJoinWorkerThread[] ws = workers;
+ if (ws != null) {
+ for (ForkJoinWorkerThread w : ws) {
+ if (w != null) {
+ w.terminate = true;
+ if (pass > 0) {
+ w.cancelTasks();
+ if (pass > 1 && !w.isInterrupted()) {
+ try {
+ w.interrupt();
+ } catch (SecurityException ignore) {
+ }
}
}
}
}
+ terminateWaiters();
+ }
+ }
+ }
+
+ /**
+ * Polls and cancels all submissions. Called only during termination.
+ */
+ private void cancelSubmissions() {
+ while (queueBase != queueTop) {
+ ForkJoinTask> task = pollSubmission();
+ if (task != null) {
+ try {
+ task.cancel(false);
+ } catch (Throwable ignore) {
+ }
}
}
}
/**
- * Clears out and cancels submissions, ignoring exceptions.
+ * Tries to set the termination status of waiting workers, and
+ * then wakes them up (after which they will terminate).
*/
- private void cancelSubmissions() {
- ForkJoinTask> task;
- while ((task = submissionQueue.poll()) != null) {
- try {
- task.cancel(false);
- } catch (Throwable ignore) {
+ private void terminateWaiters() {
+ ForkJoinWorkerThread[] ws = workers;
+ if (ws != null) {
+ ForkJoinWorkerThread w; long c; int i, e;
+ int n = ws.length;
+ while ((i = ~(e = (int)(c = ctl)) & SMASK) < n &&
+ (w = ws[i]) != null && w.eventCount == (e & E_MASK)) {
+ if (UNSAFE.compareAndSwapLong(this, ctlOffset, c,
+ (long)(w.nextWait & E_MASK) |
+ ((c + AC_UNIT) & AC_MASK) |
+ (c & (TC_MASK|STOP_BIT)))) {
+ w.terminate = true;
+ w.eventCount = e + EC_UNIT;
+ if (w.parked)
+ UNSAFE.unpark(w);
+ }
}
}
}
- // misc support for ForkJoinWorkerThread
+ // misc ForkJoinWorkerThread support
/**
- * Returns pool number.
+ * Increment or decrement quiescerCount. Needed only to prevent
+ * triggering shutdown if a worker is transiently inactive while
+ * checking quiescence.
+ *
+ * @param delta 1 for increment, -1 for decrement
*/
- final int getPoolNumber() {
- return poolNumber;
+ final void addQuiescerCount(int delta) {
+ int c;
+ do {} while(!UNSAFE.compareAndSwapInt(this, quiescerCountOffset,
+ c = quiescerCount, c + delta));
}
/**
- * Tries to accumulate steal count from a worker, clearing
- * the worker's value if successful.
+ * Directly increment or decrement active count without
+ * queuing. This method is used to transiently assert inactivation
+ * while checking quiescence.
*
- * @return true if worker steal count now zero
+ * @param delta 1 for increment, -1 for decrement
*/
- final boolean tryAccumulateStealCount(ForkJoinWorkerThread w) {
- int sc = w.stealCount;
- long c = stealCount;
- // CAS even if zero, for fence effects
- if (UNSAFE.compareAndSwapLong(this, stealCountOffset, c, c + sc)) {
- if (sc != 0)
- w.stealCount = 0;
- return true;
- }
- return sc == 0;
+ final void addActiveCount(int delta) {
+ long d = delta < 0 ? -AC_UNIT : AC_UNIT;
+ long c;
+ do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset, c = ctl,
+ ((c + d) & AC_MASK) |
+ (c & ~AC_MASK)));
}
/**
@@ -1259,16 +1382,17 @@ public class ForkJoinPool extends AbstractExecutorService {
* active thread.
*/
final int idlePerActive() {
- int pc = parallelism; // use parallelism, not rc
- int ac = runState; // no mask -- artificially boosts during shutdown
- // Use exact results for small values, saturate past 4
- return ((pc <= ac) ? 0 :
- (pc >>> 1 <= ac) ? 1 :
- (pc >>> 2 <= ac) ? 3 :
- pc >>> 3);
+ // Approximate at powers of two for small values, saturate past 4
+ int p = parallelism;
+ int a = p + (int)(ctl >> AC_SHIFT);
+ return (a > (p >>>= 1) ? 0 :
+ a > (p >>>= 1) ? 1 :
+ a > (p >>>= 1) ? 2 :
+ a > (p >>>= 1) ? 4 :
+ 8);
}
- // Public and protected methods
+ // Exported methods
// Constructors
@@ -1337,49 +1461,42 @@ public class ForkJoinPool extends AbstractExecutorService {
checkPermission();
if (factory == null)
throw new NullPointerException();
- if (parallelism <= 0 || parallelism > MAX_WORKERS)
+ if (parallelism <= 0 || parallelism > MAX_ID)
throw new IllegalArgumentException();
this.parallelism = parallelism;
this.factory = factory;
this.ueh = handler;
this.locallyFifo = asyncMode;
- int arraySize = initialArraySizeFor(parallelism);
- this.workers = new ForkJoinWorkerThread[arraySize];
- this.submissionQueue = new LinkedTransferQueue>();
- this.workerLock = new ReentrantLock();
- this.termination = new Phaser(1);
- this.poolNumber = poolNumberGenerator.incrementAndGet();
- }
-
- /**
- * Returns initial power of two size for workers array.
- * @param pc the initial parallelism level
- */
- private static int initialArraySizeFor(int pc) {
- // If possible, initially allocate enough space for one spare
- int size = pc < MAX_WORKERS ? pc + 1 : MAX_WORKERS;
- // See Hackers Delight, sec 3.2. We know MAX_WORKERS < (1 >>> 16)
- size |= size >>> 1;
- size |= size >>> 2;
- size |= size >>> 4;
- size |= size >>> 8;
- return size + 1;
+ long np = (long)(-parallelism); // offset ctl counts
+ this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
+ this.submissionQueue = new ForkJoinTask>[INITIAL_QUEUE_CAPACITY];
+ // initialize workers array with room for 2*parallelism if possible
+ int n = parallelism << 1;
+ if (n >= MAX_ID)
+ n = MAX_ID;
+ else { // See Hackers Delight, sec 3.2, where n < (1 << 16)
+ n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8;
+ }
+ workers = new ForkJoinWorkerThread[n + 1];
+ this.submissionLock = new ReentrantLock();
+ this.termination = submissionLock.newCondition();
+ StringBuilder sb = new StringBuilder("ForkJoinPool-");
+ sb.append(poolNumberGenerator.incrementAndGet());
+ sb.append("-worker-");
+ this.workerNamePrefix = sb.toString();
}
// Execution methods
- /**
- * Submits task and creates, starts, or resumes some workers if necessary
- */
- private void doSubmit(ForkJoinTask task) {
- submissionQueue.offer(task);
- int c; // try to increment event count -- CAS failure OK
- UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
- helpMaintainParallelism();
- }
-
/**
* Performs the given task, returning its result upon completion.
+ * If the computation encounters an unchecked Exception or Error,
+ * it is rethrown as the outcome of this invocation. Rethrown
+ * exceptions behave in the same way as regular exceptions, but,
+ * when possible, contain stack traces (as displayed for example
+ * using {@code ex.printStackTrace()}) of both the current thread
+ * as well as the thread actually encountering the exception;
+ * minimally only the latter.
*
* @param task the task
* @return the task's result
@@ -1388,16 +1505,16 @@ public class ForkJoinPool extends AbstractExecutorService {
* scheduled for execution
*/
public T invoke(ForkJoinTask task) {
+ Thread t = Thread.currentThread();
if (task == null)
throw new NullPointerException();
- if (runState >= SHUTDOWN)
+ if (shutdown)
throw new RejectedExecutionException();
- Thread t = Thread.currentThread();
if ((t instanceof ForkJoinWorkerThread) &&
((ForkJoinWorkerThread)t).pool == this)
return task.invoke(); // bypass submit if in same pool
else {
- doSubmit(task);
+ addSubmission(task);
return task.join();
}
}
@@ -1407,14 +1524,15 @@ public class ForkJoinPool extends AbstractExecutorService {
* computation in the current pool, else submits as external task.
*/
private void forkOrSubmit(ForkJoinTask task) {
- if (runState >= SHUTDOWN)
- throw new RejectedExecutionException();
+ ForkJoinWorkerThread w;
Thread t = Thread.currentThread();
+ if (shutdown)
+ throw new RejectedExecutionException();
if ((t instanceof ForkJoinWorkerThread) &&
- ((ForkJoinWorkerThread)t).pool == this)
- task.fork();
+ (w = (ForkJoinWorkerThread)t).pool == this)
+ w.pushTask(task);
else
- doSubmit(task);
+ addSubmission(task);
}
/**
@@ -1571,7 +1689,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of worker threads
*/
public int getPoolSize() {
- return workerCounts >>> TOTAL_COUNT_SHIFT;
+ return parallelism + (short)(ctl >>> TC_SHIFT);
}
/**
@@ -1593,7 +1711,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of worker threads
*/
public int getRunningThreadCount() {
- return workerCounts & RUNNING_COUNT_MASK;
+ int r = parallelism + (int)(ctl >> AC_SHIFT);
+ return r <= 0? 0 : r; // suppress momentarily negative values
}
/**
@@ -1604,7 +1723,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of active threads
*/
public int getActiveThreadCount() {
- return runState & ACTIVE_COUNT_MASK;
+ int r = parallelism + (int)(ctl >> AC_SHIFT) + blockedCount;
+ return r <= 0? 0 : r; // suppress momentarily negative values
}
/**
@@ -1619,7 +1739,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if all threads are currently idle
*/
public boolean isQuiescent() {
- return (runState & ACTIVE_COUNT_MASK) == 0;
+ return parallelism + (int)(ctl >> AC_SHIFT) + blockedCount == 0;
}
/**
@@ -1649,21 +1769,25 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
public long getQueuedTaskCount() {
long count = 0;
- for (ForkJoinWorkerThread w : workers)
- if (w != null)
- count += w.getQueueSize();
+ ForkJoinWorkerThread[] ws;
+ if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
+ (ws = workers) != null) {
+ for (ForkJoinWorkerThread w : ws)
+ if (w != null)
+ count -= w.queueBase - w.queueTop; // must read base first
+ }
return count;
}
/**
* Returns an estimate of the number of tasks submitted to this
- * pool that have not yet begun executing. This method takes time
- * proportional to the number of submissions.
+ * pool that have not yet begun executing. This method may take
+ * time proportional to the number of submissions.
*
* @return the number of queued submissions
*/
public int getQueuedSubmissionCount() {
- return submissionQueue.size();
+ return -queueBase + queueTop;
}
/**
@@ -1673,7 +1797,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if there are any queued submissions
*/
public boolean hasQueuedSubmissions() {
- return !submissionQueue.isEmpty();
+ return queueBase != queueTop;
}
/**
@@ -1684,7 +1808,19 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the next submission, or {@code null} if none
*/
protected ForkJoinTask> pollSubmission() {
- return submissionQueue.poll();
+ ForkJoinTask> t; ForkJoinTask>[] q; int b, i;
+ while ((b = queueBase) != queueTop &&
+ (q = submissionQueue) != null &&
+ (i = (q.length - 1) & b) >= 0) {
+ long u = (i << ASHIFT) + ABASE;
+ if ((t = q[i]) != null &&
+ queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ queueBase = b + 1;
+ return t;
+ }
+ }
+ return null;
}
/**
@@ -1705,10 +1841,21 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of elements transferred
*/
protected int drainTasksTo(Collection super ForkJoinTask>> c) {
- int count = submissionQueue.drainTo(c);
- for (ForkJoinWorkerThread w : workers)
- if (w != null)
- count += w.drainTasksTo(c);
+ int count = 0;
+ while (queueBase != queueTop) {
+ ForkJoinTask> t = pollSubmission();
+ if (t != null) {
+ c.add(t);
+ ++count;
+ }
+ }
+ ForkJoinWorkerThread[] ws;
+ if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
+ (ws = workers) != null) {
+ for (ForkJoinWorkerThread w : ws)
+ if (w != null)
+ count += w.drainTasksTo(c);
+ }
return count;
}
@@ -1723,14 +1870,20 @@ public class ForkJoinPool extends AbstractExecutorService {
long st = getStealCount();
long qt = getQueuedTaskCount();
long qs = getQueuedSubmissionCount();
- int wc = workerCounts;
- int tc = wc >>> TOTAL_COUNT_SHIFT;
- int rc = wc & RUNNING_COUNT_MASK;
int pc = parallelism;
- int rs = runState;
- int ac = rs & ACTIVE_COUNT_MASK;
+ long c = ctl;
+ int tc = pc + (short)(c >>> TC_SHIFT);
+ int rc = pc + (int)(c >> AC_SHIFT);
+ if (rc < 0) // ignore transient negative
+ rc = 0;
+ int ac = rc + blockedCount;
+ String level;
+ if ((c & STOP_BIT) != 0)
+ level = (tc == 0)? "Terminated" : "Terminating";
+ else
+ level = shutdown? "Shutting down" : "Running";
return super.toString() +
- "[" + runLevelToString(rs) +
+ "[" + level +
", parallelism = " + pc +
", size = " + tc +
", active = " + ac +
@@ -1741,13 +1894,6 @@ public class ForkJoinPool extends AbstractExecutorService {
"]";
}
- private static String runLevelToString(int s) {
- return ((s & TERMINATED) != 0 ? "Terminated" :
- ((s & TERMINATING) != 0 ? "Terminating" :
- ((s & SHUTDOWN) != 0 ? "Shutting down" :
- "Running")));
- }
-
/**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
@@ -1762,7 +1908,7 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
public void shutdown() {
checkPermission();
- advanceRunLevel(SHUTDOWN);
+ shutdown = true;
tryTerminate(false);
}
@@ -1784,6 +1930,7 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
public List shutdownNow() {
checkPermission();
+ shutdown = true;
tryTerminate(true);
return Collections.emptyList();
}
@@ -1794,7 +1941,9 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if all tasks have completed following shut down
*/
public boolean isTerminated() {
- return runState >= TERMINATED;
+ long c = ctl;
+ return ((c & STOP_BIT) != 0L &&
+ (short)(c >>> TC_SHIFT) == -parallelism);
}
/**
@@ -1811,14 +1960,16 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if terminating but not yet terminated
*/
public boolean isTerminating() {
- return (runState & (TERMINATING|TERMINATED)) == TERMINATING;
+ long c = ctl;
+ return ((c & STOP_BIT) != 0L &&
+ (short)(c >>> TC_SHIFT) != -parallelism);
}
/**
* Returns true if terminating or terminated. Used by ForkJoinWorkerThread.
*/
final boolean isAtLeastTerminating() {
- return runState >= TERMINATING;
+ return (ctl & STOP_BIT) != 0L;
}
/**
@@ -1827,7 +1978,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if this pool has been shut down
*/
public boolean isShutdown() {
- return runState >= SHUTDOWN;
+ return shutdown;
}
/**
@@ -1843,12 +1994,20 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.submissionLock;
+ lock.lock();
try {
- termination.awaitAdvanceInterruptibly(0, timeout, unit);
- } catch (TimeoutException ex) {
- return false;
+ for (;;) {
+ if (isTerminated())
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = termination.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
}
- return true;
}
/**
@@ -1859,13 +2018,15 @@ public class ForkJoinPool extends AbstractExecutorService {
* {@code isReleasable} must return {@code true} if blocking is
* not necessary. Method {@code block} blocks the current thread
* if necessary (perhaps internally invoking {@code isReleasable}
- * before actually blocking). The unusual methods in this API
- * accommodate synchronizers that may, but don't usually, block
- * for long periods. Similarly, they allow more efficient internal
- * handling of cases in which additional workers may be, but
- * usually are not, needed to ensure sufficient parallelism.
- * Toward this end, implementations of method {@code isReleasable}
- * must be amenable to repeated invocation.
+ * before actually blocking). These actions are performed by any
+ * thread invoking {@link ForkJoinPool#managedBlock}. The
+ * unusual methods in this API accommodate synchronizers that may,
+ * but don't usually, block for long periods. Similarly, they
+ * allow more efficient internal handling of cases in which
+ * additional workers may be, but usually are not, needed to
+ * ensure sufficient parallelism. Toward this end,
+ * implementations of method {@code isReleasable} must be amenable
+ * to repeated invocation.
*
* For example, here is a ManagedBlocker based on a
* ReentrantLock:
@@ -1967,29 +2128,47 @@ public class ForkJoinPool extends AbstractExecutorService {
}
// Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE;
+ private static final long ctlOffset;
+ private static final long stealCountOffset;
+ private static final long blockedCountOffset;
+ private static final long quiescerCountOffset;
+ private static final long scanGuardOffset;
+ private static final long nextWorkerNumberOffset;
+ private static final long ABASE;
+ private static final int ASHIFT;
- private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
- private static final long workerCountsOffset =
- objectFieldOffset("workerCounts", ForkJoinPool.class);
- private static final long runStateOffset =
- objectFieldOffset("runState", ForkJoinPool.class);
- private static final long eventCountOffset =
- objectFieldOffset("eventCount", ForkJoinPool.class);
- private static final long eventWaitersOffset =
- objectFieldOffset("eventWaiters", ForkJoinPool.class);
- private static final long stealCountOffset =
- objectFieldOffset("stealCount", ForkJoinPool.class);
- private static final long spareWaitersOffset =
- objectFieldOffset("spareWaiters", ForkJoinPool.class);
-
- private static long objectFieldOffset(String field, Class> klazz) {
+ static {
+ poolNumberGenerator = new AtomicInteger();
+ workerSeedGenerator = new Random();
+ modifyThreadPermission = new RuntimePermission("modifyThread");
+ defaultForkJoinWorkerThreadFactory =
+ new DefaultForkJoinWorkerThreadFactory();
+ int s;
try {
- return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
- } catch (NoSuchFieldException e) {
- // Convert Exception to corresponding Error
- NoSuchFieldError error = new NoSuchFieldError(field);
- error.initCause(e);
- throw error;
+ UNSAFE = sun.misc.Unsafe.getUnsafe();
+ Class k = ForkJoinPool.class;
+ ctlOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("ctl"));
+ stealCountOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("stealCount"));
+ blockedCountOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("blockedCount"));
+ quiescerCountOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("quiescerCount"));
+ scanGuardOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("scanGuard"));
+ nextWorkerNumberOffset = UNSAFE.objectFieldOffset
+ (k.getDeclaredField("nextWorkerNumber"));
+ Class a = ForkJoinTask[].class;
+ ABASE = UNSAFE.arrayBaseOffset(a);
+ s = UNSAFE.arrayIndexScale(a);
+ } catch (Exception e) {
+ throw new Error(e);
}
+ if ((s & (s-1)) != 0)
+ throw new Error("data type scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
}
+
}
diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
index b02323ffd6d..ee8ba8fcfab 100644
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
@@ -41,7 +41,8 @@ import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
import java.util.Map;
-import java.util.WeakHashMap;
+import java.lang.ref.WeakReference;
+import java.lang.ref.ReferenceQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
@@ -52,6 +53,8 @@ import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantLock;
+import java.lang.reflect.Constructor;
/**
* Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -95,7 +98,11 @@ import java.util.concurrent.TimeoutException;
* rethrown to callers attempting to join them. These exceptions may
* additionally include {@link RejectedExecutionException} stemming
* from internal resource exhaustion, such as failure to allocate
- * internal task queues.
+ * internal task queues. Rethrown exceptions behave in the same way as
+ * regular exceptions, but, when possible, contain stack traces (as
+ * displayed for example using {@code ex.printStackTrace()}) of both
+ * the thread that initiated the computation as well as the thread
+ * actually encountering the exception; minimally only the latter.
*
*
The primary method for awaiting completion and extracting
* results of a task is {@link #join}, but there are several variants:
@@ -192,8 +199,7 @@ public abstract class ForkJoinTask implements Future, Serializable {
* status maintenance (2) execution and awaiting completion (3)
* user-level methods that additionally report results. This is
* sometimes hard to see because this file orders exported methods
- * in a way that flows well in javadocs. In particular, most
- * join mechanics are in method quietlyJoin, below.
+ * in a way that flows well in javadocs.
*/
/*
@@ -215,91 +221,67 @@ public abstract class ForkJoinTask implements Future, Serializable {
/** The run status of this task */
volatile int status; // accessed directly by pool and workers
-
private static final int NORMAL = -1;
private static final int CANCELLED = -2;
private static final int EXCEPTIONAL = -3;
private static final int SIGNAL = 1;
- /**
- * Table of exceptions thrown by tasks, to enable reporting by
- * callers. Because exceptions are rare, we don't directly keep
- * them with task objects, but instead use a weak ref table. Note
- * that cancellation exceptions don't appear in the table, but are
- * instead recorded as status values.
- * TODO: Use ConcurrentReferenceHashMap
- */
- static final Map, Throwable> exceptionMap =
- Collections.synchronizedMap
- (new WeakHashMap, Throwable>());
-
- // Maintaining completion status
-
/**
* Marks completion and wakes up threads waiting to join this task,
* also clearing signal request bits.
*
* @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
+ * @return completion status on exit
*/
- private void setCompletion(int completion) {
- int s;
- while ((s = status) >= 0) {
+ private int setCompletion(int completion) {
+ for (int s;;) {
+ if ((s = status) < 0)
+ return s;
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
if (s != 0)
synchronized (this) { notifyAll(); }
- break;
+ return completion;
}
}
}
/**
- * Records exception and sets exceptional completion.
+ * Tries to block a worker thread until completed or timed out.
+ * Uses Object.wait time argument conventions.
+ * May fail on contention or interrupt.
*
- * @return status on exit
+ * @param millis if > 0, wait time.
*/
- private void setExceptionalCompletion(Throwable rex) {
- exceptionMap.put(this, rex);
- setCompletion(EXCEPTIONAL);
- }
-
- /**
- * Blocks a worker thread until completed or timed out. Called
- * only by pool.
- */
- final void internalAwaitDone(long millis, int nanos) {
- int s = status;
- if ((s == 0 &&
- UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL)) ||
- s > 0) {
- try { // the odd construction reduces lock bias effects
+ final void tryAwaitDone(long millis) {
+ int s;
+ try {
+ if (((s = status) > 0 ||
+ (s == 0 &&
+ UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL))) &&
+ status > 0) {
synchronized (this) {
if (status > 0)
- wait(millis, nanos);
- else
- notifyAll();
+ wait(millis);
}
- } catch (InterruptedException ie) {
- cancelIfTerminating();
}
+ } catch (InterruptedException ie) {
+ // caller must check termination
}
}
/**
* Blocks a non-worker-thread until completion.
+ * @return status upon completion
*/
- private void externalAwaitDone() {
- if (status >= 0) {
+ private int externalAwaitDone() {
+ int s;
+ if ((s = status) >= 0) {
boolean interrupted = false;
synchronized (this) {
- for (;;) {
- int s = status;
+ while ((s = status) >= 0) {
if (s == 0)
UNSAFE.compareAndSwapInt(this, statusOffset,
0, SIGNAL);
- else if (s < 0) {
- notifyAll();
- break;
- }
else {
try {
wait();
@@ -312,53 +294,308 @@ public abstract class ForkJoinTask implements Future, Serializable {
if (interrupted)
Thread.currentThread().interrupt();
}
+ return s;
}
/**
* Blocks a non-worker-thread until completion or interruption or timeout.
*/
- private void externalInterruptibleAwaitDone(boolean timed, long nanos)
+ private int externalInterruptibleAwaitDone(long millis)
throws InterruptedException {
+ int s;
if (Thread.interrupted())
throw new InterruptedException();
- if (status >= 0) {
- long startTime = timed ? System.nanoTime() : 0L;
+ if ((s = status) >= 0) {
synchronized (this) {
- for (;;) {
- long nt;
- int s = status;
+ while ((s = status) >= 0) {
if (s == 0)
UNSAFE.compareAndSwapInt(this, statusOffset,
0, SIGNAL);
- else if (s < 0) {
- notifyAll();
+ else {
+ wait(millis);
+ if (millis > 0L)
+ break;
+ }
+ }
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Primary execution method for stolen tasks. Unless done, calls
+ * exec and records status if completed, but doesn't wait for
+ * completion otherwise.
+ */
+ final void doExec() {
+ if (status >= 0) {
+ boolean completed;
+ try {
+ completed = exec();
+ } catch (Throwable rex) {
+ setExceptionalCompletion(rex);
+ return;
+ }
+ if (completed)
+ setCompletion(NORMAL); // must be outside try block
+ }
+ }
+
+ /**
+ * Primary mechanics for join, get, quietlyJoin.
+ * @return status upon completion
+ */
+ private int doJoin() {
+ Thread t; ForkJoinWorkerThread w; int s; boolean completed;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
+ if ((s = status) < 0)
+ return s;
+ if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) {
+ try {
+ completed = exec();
+ } catch (Throwable rex) {
+ return setExceptionalCompletion(rex);
+ }
+ if (completed)
+ return setCompletion(NORMAL);
+ }
+ return w.joinTask(this);
+ }
+ else
+ return externalAwaitDone();
+ }
+
+ /**
+ * Primary mechanics for invoke, quietlyInvoke.
+ * @return status upon completion
+ */
+ private int doInvoke() {
+ int s; boolean completed;
+ if ((s = status) < 0)
+ return s;
+ try {
+ completed = exec();
+ } catch (Throwable rex) {
+ return setExceptionalCompletion(rex);
+ }
+ if (completed)
+ return setCompletion(NORMAL);
+ else
+ return doJoin();
+ }
+
+ // Exception table support
+
+ /**
+ * Table of exceptions thrown by tasks, to enable reporting by
+ * callers. Because exceptions are rare, we don't directly keep
+ * them with task objects, but instead use a weak ref table. Note
+ * that cancellation exceptions don't appear in the table, but are
+ * instead recorded as status values.
+ *
+ * Note: These statics are initialized below in static block.
+ */
+ private static final ExceptionNode[] exceptionTable;
+ private static final ReentrantLock exceptionTableLock;
+ private static final ReferenceQueue exceptionTableRefQueue;
+
+ /**
+ * Fixed capacity for exceptionTable.
+ */
+ private static final int EXCEPTION_MAP_CAPACITY = 32;
+
+ /**
+ * Key-value nodes for exception table. The chained hash table
+ * uses identity comparisons, full locking, and weak references
+ * for keys. The table has a fixed capacity because it only
+ * maintains task exceptions long enough for joiners to access
+ * them, so should never become very large for sustained
+ * periods. However, since we do not know when the last joiner
+ * completes, we must use weak references and expunge them. We do
+ * so on each operation (hence full locking). Also, some thread in
+ * any ForkJoinPool will call helpExpungeStaleExceptions when its
+ * pool becomes isQuiescent.
+ */
+ static final class ExceptionNode extends WeakReference>{
+ final Throwable ex;
+ ExceptionNode next;
+ final long thrower; // use id not ref to avoid weak cycles
+ ExceptionNode(ForkJoinTask> task, Throwable ex, ExceptionNode next) {
+ super(task, exceptionTableRefQueue);
+ this.ex = ex;
+ this.next = next;
+ this.thrower = Thread.currentThread().getId();
+ }
+ }
+
+ /**
+ * Records exception and sets exceptional completion.
+ *
+ * @return status on exit
+ */
+ private int setExceptionalCompletion(Throwable ex) {
+ int h = System.identityHashCode(this);
+ final ReentrantLock lock = exceptionTableLock;
+ lock.lock();
+ try {
+ expungeStaleExceptions();
+ ExceptionNode[] t = exceptionTable;
+ int i = h & (t.length - 1);
+ for (ExceptionNode e = t[i]; ; e = e.next) {
+ if (e == null) {
+ t[i] = new ExceptionNode(this, ex, t[i]);
+ break;
+ }
+ if (e.get() == this) // already present
+ break;
+ }
+ } finally {
+ lock.unlock();
+ }
+ return setCompletion(EXCEPTIONAL);
+ }
+
+ /**
+ * Removes exception node and clears status
+ */
+ private void clearExceptionalCompletion() {
+ int h = System.identityHashCode(this);
+ final ReentrantLock lock = exceptionTableLock;
+ lock.lock();
+ try {
+ ExceptionNode[] t = exceptionTable;
+ int i = h & (t.length - 1);
+ ExceptionNode e = t[i];
+ ExceptionNode pred = null;
+ while (e != null) {
+ ExceptionNode next = e.next;
+ if (e.get() == this) {
+ if (pred == null)
+ t[i] = next;
+ else
+ pred.next = next;
+ break;
+ }
+ pred = e;
+ e = next;
+ }
+ expungeStaleExceptions();
+ status = 0;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns a rethrowable exception for the given task, if
+ * available. To provide accurate stack traces, if the exception
+ * was not thrown by the current thread, we try to create a new
+ * exception of the same type as the one thrown, but with the
+ * recorded exception as its cause. If there is no such
+ * constructor, we instead try to use a no-arg constructor,
+ * followed by initCause, to the same effect. If none of these
+ * apply, or any fail due to other exceptions, we return the
+ * recorded exception, which is still correct, although it may
+ * contain a misleading stack trace.
+ *
+ * @return the exception, or null if none
+ */
+ private Throwable getThrowableException() {
+ if (status != EXCEPTIONAL)
+ return null;
+ int h = System.identityHashCode(this);
+ ExceptionNode e;
+ final ReentrantLock lock = exceptionTableLock;
+ lock.lock();
+ try {
+ expungeStaleExceptions();
+ ExceptionNode[] t = exceptionTable;
+ e = t[h & (t.length - 1)];
+ while (e != null && e.get() != this)
+ e = e.next;
+ } finally {
+ lock.unlock();
+ }
+ Throwable ex;
+ if (e == null || (ex = e.ex) == null)
+ return null;
+ if (e.thrower != Thread.currentThread().getId()) {
+ Class ec = ex.getClass();
+ try {
+ Constructor> noArgCtor = null;
+ Constructor>[] cs = ec.getConstructors();// public ctors only
+ for (int i = 0; i < cs.length; ++i) {
+ Constructor> c = cs[i];
+ Class>[] ps = c.getParameterTypes();
+ if (ps.length == 0)
+ noArgCtor = c;
+ else if (ps.length == 1 && ps[0] == Throwable.class)
+ return (Throwable)(c.newInstance(ex));
+ }
+ if (noArgCtor != null) {
+ Throwable wx = (Throwable)(noArgCtor.newInstance());
+ wx.initCause(ex);
+ return wx;
+ }
+ } catch (Exception ignore) {
+ }
+ }
+ return ex;
+ }
+
+ /**
+ * Poll stale refs and remove them. Call only while holding lock.
+ */
+ private static void expungeStaleExceptions() {
+ for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
+ if (x instanceof ExceptionNode) {
+ ForkJoinTask> key = ((ExceptionNode)x).get();
+ ExceptionNode[] t = exceptionTable;
+ int i = System.identityHashCode(key) & (t.length - 1);
+ ExceptionNode e = t[i];
+ ExceptionNode pred = null;
+ while (e != null) {
+ ExceptionNode next = e.next;
+ if (e == x) {
+ if (pred == null)
+ t[i] = next;
+ else
+ pred.next = next;
break;
}
- else if (!timed)
- wait();
- else if ((nt = nanos - (System.nanoTime()-startTime)) > 0L)
- wait(nt / 1000000, (int)(nt % 1000000));
- else
- break;
+ pred = e;
+ e = next;
}
}
}
}
/**
- * Unless done, calls exec and records status if completed, but
- * doesn't wait for completion otherwise. Primary execution method
- * for ForkJoinWorkerThread.
+ * If lock is available, poll stale refs and remove them.
+ * Called from ForkJoinPool when pools become quiescent.
*/
- final void quietlyExec() {
- try {
- if (status < 0 || !exec())
- return;
- } catch (Throwable rex) {
- setExceptionalCompletion(rex);
- return;
+ static final void helpExpungeStaleExceptions() {
+ final ReentrantLock lock = exceptionTableLock;
+ if (lock.tryLock()) {
+ try {
+ expungeStaleExceptions();
+ } finally {
+ lock.unlock();
+ }
}
- setCompletion(NORMAL); // must be outside try block
+ }
+
+ /**
+ * Report the result of invoke or join; called only upon
+ * non-normal return of internal versions.
+ */
+ private V reportResult() {
+ int s; Throwable ex;
+ if ((s = status) == CANCELLED)
+ throw new CancellationException();
+ if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
+ UNSAFE.throwException(ex);
+ return getRawResult();
}
// public methods
@@ -399,11 +636,10 @@ public abstract class ForkJoinTask implements Future, Serializable {
* @return the computed result
*/
public final V join() {
- quietlyJoin();
- Throwable ex;
- if (status < NORMAL && (ex = getException()) != null)
- UNSAFE.throwException(ex);
- return getRawResult();
+ if (doJoin() != NORMAL)
+ return reportResult();
+ else
+ return getRawResult();
}
/**
@@ -415,11 +651,10 @@ public abstract class ForkJoinTask implements Future, Serializable {
* @return the computed result
*/
public final V invoke() {
- quietlyInvoke();
- Throwable ex;
- if (status < NORMAL && (ex = getException()) != null)
- UNSAFE.throwException(ex);
- return getRawResult();
+ if (doInvoke() != NORMAL)
+ return reportResult();
+ else
+ return getRawResult();
}
/**
@@ -483,22 +718,16 @@ public abstract class ForkJoinTask implements Future, Serializable {
}
else if (i != 0)
t.fork();
- else {
- t.quietlyInvoke();
- if (ex == null && t.status < NORMAL)
- ex = t.getException();
- }
+ else if (t.doInvoke() < NORMAL && ex == null)
+ ex = t.getException();
}
for (int i = 1; i <= last; ++i) {
ForkJoinTask> t = tasks[i];
if (t != null) {
if (ex != null)
t.cancel(false);
- else {
- t.quietlyJoin();
- if (ex == null && t.status < NORMAL)
- ex = t.getException();
- }
+ else if (t.doJoin() < NORMAL && ex == null)
+ ex = t.getException();
}
}
if (ex != null)
@@ -546,22 +775,16 @@ public abstract class ForkJoinTask implements Future, Serializable {
}
else if (i != 0)
t.fork();
- else {
- t.quietlyInvoke();
- if (ex == null && t.status < NORMAL)
- ex = t.getException();
- }
+ else if (t.doInvoke() < NORMAL && ex == null)
+ ex = t.getException();
}
for (int i = 1; i <= last; ++i) {
ForkJoinTask> t = ts.get(i);
if (t != null) {
if (ex != null)
t.cancel(false);
- else {
- t.quietlyJoin();
- if (ex == null && t.status < NORMAL)
- ex = t.getException();
- }
+ else if (t.doJoin() < NORMAL && ex == null)
+ ex = t.getException();
}
}
if (ex != null)
@@ -597,8 +820,7 @@ public abstract class ForkJoinTask implements Future, Serializable {
* @return {@code true} if this task is now cancelled
*/
public boolean cancel(boolean mayInterruptIfRunning) {
- setCompletion(CANCELLED);
- return status == CANCELLED;
+ return setCompletion(CANCELLED) == CANCELLED;
}
/**
@@ -614,21 +836,6 @@ public abstract class ForkJoinTask implements Future, Serializable {
}
}
- /**
- * Cancels if current thread is a terminating worker thread,
- * ignoring any exceptions thrown by cancel.
- */
- final void cancelIfTerminating() {
- Thread t = Thread.currentThread();
- if ((t instanceof ForkJoinWorkerThread) &&
- ((ForkJoinWorkerThread) t).isTerminating()) {
- try {
- cancel(false);
- } catch (Throwable ignore) {
- }
- }
- }
-
public final boolean isDone() {
return status < 0;
}
@@ -668,7 +875,7 @@ public abstract class ForkJoinTask implements Future, Serializable {
int s = status;
return ((s >= NORMAL) ? null :
(s == CANCELLED) ? new CancellationException() :
- exceptionMap.get(this));
+ getThrowableException());
}
/**
@@ -726,19 +933,13 @@ public abstract class ForkJoinTask implements Future, Serializable {
* member of a ForkJoinPool and was interrupted while waiting
*/
public final V get() throws InterruptedException, ExecutionException {
- Thread t = Thread.currentThread();
- if (t instanceof ForkJoinWorkerThread)
- quietlyJoin();
- else
- externalInterruptibleAwaitDone(false, 0L);
- int s = status;
- if (s != NORMAL) {
- Throwable ex;
- if (s == CANCELLED)
- throw new CancellationException();
- if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
- throw new ExecutionException(ex);
- }
+ int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
+ doJoin() : externalInterruptibleAwaitDone(0L);
+ Throwable ex;
+ if (s == CANCELLED)
+ throw new CancellationException();
+ if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
+ throw new ExecutionException(ex);
return getRawResult();
}
@@ -758,20 +959,39 @@ public abstract class ForkJoinTask implements Future, Serializable {
*/
public final V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
- long nanos = unit.toNanos(timeout);
Thread t = Thread.currentThread();
- if (t instanceof ForkJoinWorkerThread)
- ((ForkJoinWorkerThread)t).joinTask(this, true, nanos);
- else
- externalInterruptibleAwaitDone(true, nanos);
+ if (t instanceof ForkJoinWorkerThread) {
+ ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
+ long nanos = unit.toNanos(timeout);
+ if (status >= 0) {
+ boolean completed = false;
+ if (w.unpushTask(this)) {
+ try {
+ completed = exec();
+ } catch (Throwable rex) {
+ setExceptionalCompletion(rex);
+ }
+ }
+ if (completed)
+ setCompletion(NORMAL);
+ else if (status >= 0 && nanos > 0)
+ w.pool.timedAwaitJoin(this, nanos);
+ }
+ }
+ else {
+ long millis = unit.toMillis(timeout);
+ if (millis > 0)
+ externalInterruptibleAwaitDone(millis);
+ }
int s = status;
if (s != NORMAL) {
Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
- if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+ if (s != EXCEPTIONAL)
+ throw new TimeoutException();
+ if ((ex = getThrowableException()) != null)
throw new ExecutionException(ex);
- throw new TimeoutException();
}
return getRawResult();
}
@@ -783,28 +1003,7 @@ public abstract class ForkJoinTask implements Future, Serializable {
* known to have aborted.
*/
public final void quietlyJoin() {
- Thread t;
- if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
- ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
- if (status >= 0) {
- if (w.unpushTask(this)) {
- boolean completed;
- try {
- completed = exec();
- } catch (Throwable rex) {
- setExceptionalCompletion(rex);
- return;
- }
- if (completed) {
- setCompletion(NORMAL);
- return;
- }
- }
- w.joinTask(this, false, 0L);
- }
- }
- else
- externalAwaitDone();
+ doJoin();
}
/**
@@ -813,19 +1012,7 @@ public abstract class ForkJoinTask implements Future, Serializable {
* exception.
*/
public final void quietlyInvoke() {
- if (status >= 0) {
- boolean completed;
- try {
- completed = exec();
- } catch (Throwable rex) {
- setExceptionalCompletion(rex);
- return;
- }
- if (completed)
- setCompletion(NORMAL);
- else
- quietlyJoin();
- }
+ doInvoke();
}
/**
@@ -864,8 +1051,9 @@ public abstract class ForkJoinTask implements Future, Serializable {
*/
public void reinitialize() {
if (status == EXCEPTIONAL)
- exceptionMap.remove(this);
- status = 0;
+ clearExceptionalCompletion();
+ else
+ status = 0;
}
/**
@@ -1176,23 +1364,23 @@ public abstract class ForkJoinTask implements Future, Serializable {
s.defaultReadObject();
Object ex = s.readObject();
if (ex != null)
- setExceptionalCompletion((Throwable) ex);
+ setExceptionalCompletion((Throwable)ex);
}
// Unsafe mechanics
-
- private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
- private static final long statusOffset =
- objectFieldOffset("status", ForkJoinTask.class);
-
- private static long objectFieldOffset(String field, Class> klazz) {
+ private static final sun.misc.Unsafe UNSAFE;
+ private static final long statusOffset;
+ static {
+ exceptionTableLock = new ReentrantLock();
+ exceptionTableRefQueue = new ReferenceQueue();
+ exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
try {
- return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
- } catch (NoSuchFieldException e) {
- // Convert Exception to corresponding Error
- NoSuchFieldError error = new NoSuchFieldError(field);
- error.initCause(e);
- throw error;
+ UNSAFE = sun.misc.Unsafe.getUnsafe();
+ statusOffset = UNSAFE.objectFieldOffset
+ (ForkJoinTask.class.getDeclaredField("status"));
+ } catch (Exception e) {
+ throw new Error(e);
}
}
+
}
diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
index 7d79c5190e2..2f48080a664 100644
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
@@ -35,9 +35,7 @@
package java.util.concurrent;
-import java.util.Random;
import java.util.Collection;
-import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.RejectedExecutionException;
/**
@@ -84,33 +82,38 @@ public class ForkJoinWorkerThread extends Thread {
* a footprint as possible even in programs generating huge
* numbers of tasks. To accomplish this, we shift the CAS
* arbitrating pop vs deq (steal) from being on the indices
- * ("base" and "sp") to the slots themselves (mainly via method
- * "casSlotNull()"). So, both a successful pop and deq mainly
- * entail a CAS of a slot from non-null to null. Because we rely
- * on CASes of references, we do not need tag bits on base or sp.
- * They are simple ints as used in any circular array-based queue
- * (see for example ArrayDeque). Updates to the indices must
- * still be ordered in a way that guarantees that sp == base means
- * the queue is empty, but otherwise may err on the side of
- * possibly making the queue appear nonempty when a push, pop, or
- * deq have not fully committed. Note that this means that the deq
- * operation, considered individually, is not wait-free. One thief
- * cannot successfully continue until another in-progress one (or,
- * if previously empty, a push) completes. However, in the
+ * ("queueBase" and "queueTop") to the slots themselves (mainly
+ * via method "casSlotNull()"). So, both a successful pop and deq
+ * mainly entail a CAS of a slot from non-null to null. Because
+ * we rely on CASes of references, we do not need tag bits on
+ * queueBase or queueTop. They are simple ints as used in any
+ * circular array-based queue (see for example ArrayDeque).
+ * Updates to the indices must still be ordered in a way that
+ * guarantees that queueTop == queueBase means the queue is empty,
+ * but otherwise may err on the side of possibly making the queue
+ * appear nonempty when a push, pop, or deq have not fully
+ * committed. Note that this means that the deq operation,
+ * considered individually, is not wait-free. One thief cannot
+ * successfully continue until another in-progress one (or, if
+ * previously empty, a push) completes. However, in the
* aggregate, we ensure at least probabilistic non-blockingness.
* If an attempted steal fails, a thief always chooses a different
* random victim target to try next. So, in order for one thief to
* progress, it suffices for any in-progress deq or new push on
- * any empty queue to complete. One reason this works well here is
- * that apparently-nonempty often means soon-to-be-stealable,
- * which gives threads a chance to set activation status if
- * necessary before stealing.
+ * any empty queue to complete.
*
* This approach also enables support for "async mode" where local
* task processing is in FIFO, not LIFO order; simply by using a
* version of deq rather than pop when locallyFifo is true (as set
* by the ForkJoinPool). This allows use in message-passing
- * frameworks in which tasks are never joined.
+ * frameworks in which tasks are never joined. However neither
+ * mode considers affinities, loads, cache localities, etc, so
+ * rarely provide the best possible performance on a given
+ * machine, but portably provide good throughput by averaging over
+ * these factors. (Further, even if we did try to use such
+ * information, we do not usually have a basis for exploiting
+ * it. For example, some sets of tasks profit from cache
+ * affinities, but others are harmed by cache pollution effects.)
*
* When a worker would otherwise be blocked waiting to join a
* task, it first tries a form of linear helping: Each worker
@@ -137,29 +140,26 @@ public class ForkJoinWorkerThread extends Thread {
* miss links in the chain during long-lived tasks, GC stalls etc
* (which is OK since blocking in such cases is usually a good
* idea). (4) We bound the number of attempts to find work (see
- * MAX_HELP_DEPTH) and fall back to suspending the worker and if
- * necessary replacing it with a spare (see
- * ForkJoinPool.awaitJoin).
+ * MAX_HELP) and fall back to suspending the worker and if
+ * necessary replacing it with another.
*
* Efficient implementation of these algorithms currently relies
* on an uncomfortable amount of "Unsafe" mechanics. To maintain
- * correct orderings, reads and writes of variable base require
- * volatile ordering. Variable sp does not require volatile
- * writes but still needs store-ordering, which we accomplish by
- * pre-incrementing sp before filling the slot with an ordered
- * store. (Pre-incrementing also enables backouts used in
- * joinTask.) Because they are protected by volatile base reads,
- * reads of the queue array and its slots by other threads do not
- * need volatile load semantics, but writes (in push) require
- * store order and CASes (in pop and deq) require (volatile) CAS
- * semantics. (Michael, Saraswat, and Vechev's algorithm has
- * similar properties, but without support for nulling slots.)
- * Since these combinations aren't supported using ordinary
- * volatiles, the only way to accomplish these efficiently is to
- * use direct Unsafe calls. (Using external AtomicIntegers and
- * AtomicReferenceArrays for the indices and array is
- * significantly slower because of memory locality and indirection
- * effects.)
+ * correct orderings, reads and writes of variable queueBase
+ * require volatile ordering. Variable queueTop need not be
+ * volatile because non-local reads always follow those of
+ * queueBase. Similarly, because they are protected by volatile
+ * queueBase reads, reads of the queue array and its slots by
+ * other threads do not need volatile load semantics, but writes
+ * (in push) require store order and CASes (in pop and deq)
+ * require (volatile) CAS semantics. (Michael, Saraswat, and
+ * Vechev's algorithm has similar properties, but without support
+ * for nulling slots.) Since these combinations aren't supported
+ * using ordinary volatiles, the only way to accomplish these
+ * efficiently is to use direct Unsafe calls. (Using external
+ * AtomicIntegers and AtomicReferenceArrays for the indices and
+ * array is significantly slower because of memory locality and
+ * indirection effects.)
*
* Further, performance on most platforms is very sensitive to
* placement and sizing of the (resizable) queue array. Even
@@ -167,30 +167,13 @@ public class ForkJoinWorkerThread extends Thread {
* initial size must be large enough to counteract cache
* contention effects across multiple queues (especially in the
* presence of GC cardmarking). Also, to improve thread-locality,
- * queues are initialized after starting. All together, these
- * low-level implementation choices produce as much as a factor of
- * 4 performance improvement compared to naive implementations,
- * and enable the processing of billions of tasks per second,
- * sometimes at the expense of ugliness.
+ * queues are initialized after starting.
*/
/**
- * Generator for initial random seeds for random victim
- * selection. This is used only to create initial seeds. Random
- * steals use a cheaper xorshift generator per steal attempt. We
- * expect only rare contention on seedGenerator, so just use a
- * plain Random.
+ * Mask for pool indices encoded as shorts
*/
- private static final Random seedGenerator = new Random();
-
- /**
- * The maximum stolen->joining link depth allowed in helpJoinTask.
- * Depths for legitimate chains are unbounded, but we use a fixed
- * constant to avoid (otherwise unchecked) cycles and bound
- * staleness of traversal parameters at the expense of sometimes
- * blocking when we could be helping.
- */
- private static final int MAX_HELP_DEPTH = 8;
+ private static final int SMASK = 0xffff;
/**
* Capacity of work-stealing queue array upon initialization.
@@ -200,12 +183,19 @@ public class ForkJoinWorkerThread extends Thread {
private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
/**
- * Maximum work-stealing queue array size. Must be less than or
- * equal to 1 << (31 - width of array entry) to ensure lack of
- * index wraparound. The value is set in the static block
- * at the end of this file after obtaining width.
+ * Maximum size for queue array. Must be a power of two
+ * less than or equal to 1 << (31 - width of array entry) to
+ * ensure lack of index wraparound, but is capped at a lower
+ * value to help users trap runaway computations.
*/
- private static final int MAXIMUM_QUEUE_CAPACITY;
+ private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
+
+ /**
+ * The work-stealing queue array. Size must be a power of two.
+ * Initialized when started (as oposed to when constructed), to
+ * improve memory locality.
+ */
+ ForkJoinTask>[] queue;
/**
* The pool this thread works in. Accessed directly by ForkJoinTask.
@@ -213,25 +203,19 @@ public class ForkJoinWorkerThread extends Thread {
final ForkJoinPool pool;
/**
- * The work-stealing queue array. Size must be a power of two.
- * Initialized in onStart, to improve memory locality.
+ * Index (mod queue.length) of next queue slot to push to or pop
+ * from. It is written only by owner thread, and accessed by other
+ * threads only after reading (volatile) queueBase. Both queueTop
+ * and queueBase are allowed to wrap around on overflow, but
+ * (queueTop - queueBase) still estimates size.
*/
- private ForkJoinTask>[] queue;
+ int queueTop;
/**
* Index (mod queue.length) of least valid queue slot, which is
* always the next position to steal from if nonempty.
*/
- private volatile int base;
-
- /**
- * Index (mod queue.length) of next queue slot to push to or pop
- * from. It is written only by owner thread, and accessed by other
- * threads only after reading (volatile) base. Both sp and base
- * are allowed to wrap around on overflow, but (sp - base) still
- * estimates size.
- */
- private int sp;
+ volatile int queueBase;
/**
* The index of most recent stealer, used as a hint to avoid
@@ -240,92 +224,68 @@ public class ForkJoinWorkerThread extends Thread {
* of them (usually the most current). Declared non-volatile,
* relying on other prevailing sync to keep reasonably current.
*/
- private int stealHint;
-
- /**
- * Run state of this worker. In addition to the usual run levels,
- * tracks if this worker is suspended as a spare, and if it was
- * killed (trimmed) while suspended. However, "active" status is
- * maintained separately and modified only in conjunction with
- * CASes of the pool's runState (which are currently sadly
- * manually inlined for performance.) Accessed directly by pool
- * to simplify checks for normal (zero) status.
- */
- volatile int runState;
-
- private static final int TERMINATING = 0x01;
- private static final int TERMINATED = 0x02;
- private static final int SUSPENDED = 0x04; // inactive spare
- private static final int TRIMMED = 0x08; // killed while suspended
-
- /**
- * Number of steals. Directly accessed (and reset) by
- * pool.tryAccumulateStealCount when idle.
- */
- int stealCount;
-
- /**
- * Seed for random number generator for choosing steal victims.
- * Uses Marsaglia xorshift. Must be initialized as nonzero.
- */
- private int seed;
-
- /**
- * Activity status. When true, this worker is considered active.
- * Accessed directly by pool. Must be false upon construction.
- */
- boolean active;
-
- /**
- * True if use local fifo, not default lifo, for local polling.
- * Shadows value from ForkJoinPool.
- */
- private final boolean locallyFifo;
+ int stealHint;
/**
* Index of this worker in pool array. Set once by pool before
* running, and accessed directly by pool to locate this worker in
* its workers array.
*/
- int poolIndex;
+ final int poolIndex;
/**
- * The last pool event waited for. Accessed only by pool in
- * callback methods invoked within this thread.
+ * Encoded record for pool task waits. Usages are always
+ * surrounded by volatile reads/writes
*/
- int lastEventCount;
+ int nextWait;
/**
- * Encoded index and event count of next event waiter. Accessed
- * only by ForkJoinPool for managing event waiters.
+ * Complement of poolIndex, offset by count of entries of task
+ * waits. Accessed by ForkJoinPool to manage event waiters.
*/
- volatile long nextWaiter;
+ volatile int eventCount;
/**
- * Number of times this thread suspended as spare. Accessed only
- * by pool.
+ * Seed for random number generator for choosing steal victims.
+ * Uses Marsaglia xorshift. Must be initialized as nonzero.
*/
- int spareCount;
+ int seed;
/**
- * Encoded index and count of next spare waiter. Accessed only
- * by ForkJoinPool for managing spares.
+ * Number of steals. Directly accessed (and reset) by pool when
+ * idle.
*/
- volatile int nextSpare;
+ int stealCount;
/**
- * The task currently being joined, set only when actively trying
- * to help other stealers in helpJoinTask. Written only by this
- * thread, but read by others.
+ * True if this worker should or did terminate
*/
- private volatile ForkJoinTask> currentJoin;
+ volatile boolean terminate;
+
+ /**
+ * Set to true before LockSupport.park; false on return
+ */
+ volatile boolean parked;
+
+ /**
+ * True if use local fifo, not default lifo, for local polling.
+ * Shadows value from ForkJoinPool.
+ */
+ final boolean locallyFifo;
/**
* The task most recently stolen from another worker (or
- * submission queue). Written only by this thread, but read by
- * others.
+ * submission queue). All uses are surrounded by enough volatile
+ * reads/writes to maintain as non-volatile.
*/
- private volatile ForkJoinTask> currentSteal;
+ ForkJoinTask> currentSteal;
+
+ /**
+ * The task currently being joined, set only when actively trying
+ * to help other stealers in helpJoinTask. All uses are surrounded
+ * by enough volatile reads/writes to maintain as non-volatile.
+ */
+ ForkJoinTask> currentJoin;
/**
* Creates a ForkJoinWorkerThread operating in the given pool.
@@ -334,24 +294,19 @@ public class ForkJoinWorkerThread extends Thread {
* @throws NullPointerException if pool is null
*/
protected ForkJoinWorkerThread(ForkJoinPool pool) {
+ super(pool.nextWorkerName());
this.pool = pool;
- this.locallyFifo = pool.locallyFifo;
- setDaemon(true);
- // To avoid exposing construction details to subclasses,
- // remaining initialization is in start() and onStart()
- }
-
- /**
- * Performs additional initialization and starts this thread.
- */
- final void start(int poolIndex, UncaughtExceptionHandler ueh) {
- this.poolIndex = poolIndex;
+ int k = pool.registerWorker(this);
+ poolIndex = k;
+ eventCount = ~k & SMASK; // clear wait count
+ locallyFifo = pool.locallyFifo;
+ Thread.UncaughtExceptionHandler ueh = pool.ueh;
if (ueh != null)
setUncaughtExceptionHandler(ueh);
- start();
+ setDaemon(true);
}
- // Public/protected methods
+ // Public methods
/**
* Returns the pool hosting this thread.
@@ -375,6 +330,25 @@ public class ForkJoinWorkerThread extends Thread {
return poolIndex;
}
+ // Randomization
+
+ /**
+ * Computes next value for random victim probes and backoffs.
+ * Scans don't require a very high quality generator, but also not
+ * a crummy one. Marsaglia xor-shift is cheap and works well
+ * enough. Note: This is manually inlined in FJP.scan() to avoid
+ * writes inside busy loops.
+ */
+ private int nextSeed() {
+ int r = seed;
+ r ^= r << 13;
+ r ^= r >>> 17;
+ r ^= r << 5;
+ return seed = r;
+ }
+
+ // Run State management
+
/**
* Initializes internal state after construction but before
* processing any tasks. If you override this method, you must
@@ -385,15 +359,9 @@ public class ForkJoinWorkerThread extends Thread {
* processing tasks.
*/
protected void onStart() {
- int rs = seedGenerator.nextInt();
- seed = (rs == 0) ? 1 : rs; // seed must be nonzero
-
- // Allocate name string and arrays in this thread
- String pid = Integer.toString(pool.getPoolNumber());
- String wid = Integer.toString(poolIndex);
- setName("ForkJoinPool-" + pid + "-worker-" + wid);
-
queue = new ForkJoinTask>[INITIAL_QUEUE_CAPACITY];
+ int r = pool.workerSeedGenerator.nextInt();
+ seed = (r == 0)? 1 : r; // must be nonzero
}
/**
@@ -406,16 +374,9 @@ public class ForkJoinWorkerThread extends Thread {
*/
protected void onTermination(Throwable exception) {
try {
- ForkJoinPool p = pool;
- if (active) {
- int a; // inline p.tryDecrementActiveCount
- active = false;
- do {} while (!UNSAFE.compareAndSwapInt
- (p, poolRunStateOffset, a = p.runState, a - 1));
- }
+ terminate = true;
cancelTasks();
- setTerminated();
- p.workerTerminated(this);
+ pool.deregisterWorker(this, exception);
} catch (Throwable ex) { // Shouldn't ever happen
if (exception == null) // but if so, at least rethrown
exception = ex;
@@ -434,7 +395,7 @@ public class ForkJoinWorkerThread extends Thread {
Throwable exception = null;
try {
onStart();
- mainLoop();
+ pool.work(this);
} catch (Throwable ex) {
exception = ex;
} finally {
@@ -442,81 +403,6 @@ public class ForkJoinWorkerThread extends Thread {
}
}
- // helpers for run()
-
- /**
- * Finds and executes tasks, and checks status while running.
- */
- private void mainLoop() {
- boolean ran = false; // true if ran a task on last step
- ForkJoinPool p = pool;
- for (;;) {
- p.preStep(this, ran);
- if (runState != 0)
- break;
- ran = tryExecSteal() || tryExecSubmission();
- }
- }
-
- /**
- * Tries to steal a task and execute it.
- *
- * @return true if ran a task
- */
- private boolean tryExecSteal() {
- ForkJoinTask> t;
- if ((t = scan()) != null) {
- t.quietlyExec();
- UNSAFE.putOrderedObject(this, currentStealOffset, null);
- if (sp != base)
- execLocalTasks();
- return true;
- }
- return false;
- }
-
- /**
- * If a submission exists, try to activate and run it.
- *
- * @return true if ran a task
- */
- private boolean tryExecSubmission() {
- ForkJoinPool p = pool;
- // This loop is needed in case attempt to activate fails, in
- // which case we only retry if there still appears to be a
- // submission.
- while (p.hasQueuedSubmissions()) {
- ForkJoinTask> t; int a;
- if (active || // inline p.tryIncrementActiveCount
- (active = UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
- a = p.runState, a + 1))) {
- if ((t = p.pollSubmission()) != null) {
- UNSAFE.putOrderedObject(this, currentStealOffset, t);
- t.quietlyExec();
- UNSAFE.putOrderedObject(this, currentStealOffset, null);
- if (sp != base)
- execLocalTasks();
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Runs local tasks until queue is empty or shut down. Call only
- * while active.
- */
- private void execLocalTasks() {
- while (runState == 0) {
- ForkJoinTask> t = locallyFifo ? locallyDeqTask() : popTask();
- if (t != null)
- t.quietlyExec();
- else if (sp == base)
- break;
- }
- }
-
/*
* Intrinsics-based atomic writes for queue slots. These are
* basically the same as methods in AtomicReferenceArray, but
@@ -528,10 +414,20 @@ public class ForkJoinWorkerThread extends Thread {
* because they are protected by other volatile reads and are
* confirmed by CASes.
*
- * Most uses don't actually call these methods, but instead contain
- * inlined forms that enable more predictable optimization. We
- * don't define the version of write used in pushTask at all, but
- * instead inline there a store-fenced array slot write.
+ * Most uses don't actually call these methods, but instead
+ * contain inlined forms that enable more predictable
+ * optimization. We don't define the version of write used in
+ * pushTask at all, but instead inline there a store-fenced array
+ * slot write.
+ *
+ * Also in most methods, as a performance (not correctness) issue,
+ * we'd like to encourage compilers not to arbitrarily postpone
+ * setting queueTop after writing slot. Currently there is no
+ * intrinsic for arranging this, but using Unsafe putOrderedInt
+ * may be a preferable strategy on some compilers even though its
+ * main effect is a pre-, not post- fence. To simplify possible
+ * changes, the option is left in comments next to the associated
+ * assignments.
*/
/**
@@ -540,7 +436,7 @@ public class ForkJoinWorkerThread extends Thread {
*/
private static final boolean casSlotNull(ForkJoinTask>[] q, int i,
ForkJoinTask> t) {
- return UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase, t, null);
+ return UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null);
}
/**
@@ -550,7 +446,7 @@ public class ForkJoinWorkerThread extends Thread {
*/
private static final void writeSlot(ForkJoinTask>[] q, int i,
ForkJoinTask> t) {
- UNSAFE.putObjectVolatile(q, (i << qShift) + qBase, t);
+ UNSAFE.putObjectVolatile(q, (i << ASHIFT) + ABASE, t);
}
// queue methods
@@ -561,14 +457,43 @@ public class ForkJoinWorkerThread extends Thread {
* @param t the task. Caller must ensure non-null.
*/
final void pushTask(ForkJoinTask> t) {
- ForkJoinTask>[] q = queue;
- int mask = q.length - 1; // implicit assert q != null
- int s = sp++; // ok to increment sp before slot write
- UNSAFE.putOrderedObject(q, ((s & mask) << qShift) + qBase, t);
- if ((s -= base) == 0)
- pool.signalWork(); // was empty
- else if (s == mask)
- growQueue(); // is full
+ ForkJoinTask>[] q; int s, m;
+ if ((q = queue) != null) { // ignore if queue removed
+ long u = (((s = queueTop) & (m = q.length - 1)) << ASHIFT) + ABASE;
+ UNSAFE.putOrderedObject(q, u, t);
+ queueTop = s + 1; // or use putOrderedInt
+ if ((s -= queueBase) <= 2)
+ pool.signalWork();
+ else if (s == m)
+ growQueue();
+ }
+ }
+
+ /**
+ * Creates or doubles queue array. Transfers elements by
+ * emulating steals (deqs) from old array and placing, oldest
+ * first, into new array.
+ */
+ private void growQueue() {
+ ForkJoinTask>[] oldQ = queue;
+ int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
+ if (size > MAXIMUM_QUEUE_CAPACITY)
+ throw new RejectedExecutionException("Queue capacity exceeded");
+ if (size < INITIAL_QUEUE_CAPACITY)
+ size = INITIAL_QUEUE_CAPACITY;
+ ForkJoinTask>[] q = queue = new ForkJoinTask>[size];
+ int mask = size - 1;
+ int top = queueTop;
+ int oldMask;
+ if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
+ for (int b = queueBase; b != top; ++b) {
+ long u = ((b & oldMask) << ASHIFT) + ABASE;
+ Object x = UNSAFE.getObjectVolatile(oldQ, u);
+ if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
+ UNSAFE.putObjectVolatile
+ (q, ((b & mask) << ASHIFT) + ABASE, x);
+ }
+ }
}
/**
@@ -579,35 +504,34 @@ public class ForkJoinWorkerThread extends Thread {
* @return a task, or null if none or contended
*/
final ForkJoinTask> deqTask() {
- ForkJoinTask> t;
- ForkJoinTask>[] q;
- int b, i;
- if (sp != (b = base) &&
+ ForkJoinTask> t; ForkJoinTask>[] q; int b, i;
+ if (queueTop != (b = queueBase) &&
(q = queue) != null && // must read q after b
- (t = q[i = (q.length - 1) & b]) != null && base == b &&
- UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase, t, null)) {
- base = b + 1;
+ (i = (q.length - 1) & b) >= 0 &&
+ (t = q[i]) != null && queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null)) {
+ queueBase = b + 1;
return t;
}
return null;
}
/**
- * Tries to take a task from the base of own queue. Assumes active
- * status. Called only by this thread.
+ * Tries to take a task from the base of own queue. Called only
+ * by this thread.
*
* @return a task, or null if none
*/
final ForkJoinTask> locallyDeqTask() {
+ ForkJoinTask> t; int m, b, i;
ForkJoinTask>[] q = queue;
- if (q != null) {
- ForkJoinTask> t;
- int b, i;
- while (sp != (b = base)) {
- if ((t = q[i = (q.length - 1) & b]) != null && base == b &&
- UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase,
+ if (q != null && (m = q.length - 1) >= 0) {
+ while (queueTop != (b = queueBase)) {
+ if ((t = q[i = m & b]) != null &&
+ queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE,
t, null)) {
- base = b + 1;
+ queueBase = b + 1;
return t;
}
}
@@ -616,35 +540,21 @@ public class ForkJoinWorkerThread extends Thread {
}
/**
- * Returns a popped task, or null if empty. Assumes active status.
+ * Returns a popped task, or null if empty.
* Called only by this thread.
*/
private ForkJoinTask> popTask() {
+ int m;
ForkJoinTask>[] q = queue;
- if (q != null) {
- int s;
- while ((s = sp) != base) {
- int i = (q.length - 1) & --s;
- long u = (i << qShift) + qBase; // raw offset
+ if (q != null && (m = q.length - 1) >= 0) {
+ for (int s; (s = queueTop) != queueBase;) {
+ int i = m & --s;
+ long u = (i << ASHIFT) + ABASE; // raw offset
ForkJoinTask> t = q[i];
if (t == null) // lost to stealer
break;
if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
- /*
- * Note: here and in related methods, as a
- * performance (not correctness) issue, we'd like
- * to encourage compiler not to arbitrarily
- * postpone setting sp after successful CAS.
- * Currently there is no intrinsic for arranging
- * this, but using Unsafe putOrderedInt may be a
- * preferable strategy on some compilers even
- * though its main effect is a pre-, not post-
- * fence. To simplify possible changes, the option
- * is left in comments next to the associated
- * assignments.
- */
- sp = s; // putOrderedInt may encourage more timely write
- // UNSAFE.putOrderedInt(this, spOffset, s);
+ queueTop = s; // or putOrderedInt
return t;
}
}
@@ -654,18 +564,17 @@ public class ForkJoinWorkerThread extends Thread {
/**
* Specialized version of popTask to pop only if topmost element
- * is the given task. Called only by this thread while active.
+ * is the given task. Called only by this thread.
*
* @param t the task. Caller must ensure non-null.
*/
final boolean unpushTask(ForkJoinTask> t) {
+ ForkJoinTask>[] q;
int s;
- ForkJoinTask>[] q = queue;
- if ((s = sp) != base && q != null &&
+ if ((q = queue) != null && (s = queueTop) != queueBase &&
UNSAFE.compareAndSwapObject
- (q, (((q.length - 1) & --s) << qShift) + qBase, t, null)) {
- sp = s; // putOrderedInt may encourage more timely write
- // UNSAFE.putOrderedInt(this, spOffset, s);
+ (q, (((q.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
+ queueTop = s; // or putOrderedInt
return true;
}
return false;
@@ -675,222 +584,30 @@ public class ForkJoinWorkerThread extends Thread {
* Returns next task, or null if empty or contended.
*/
final ForkJoinTask> peekTask() {
+ int m;
ForkJoinTask>[] q = queue;
- if (q == null)
+ if (q == null || (m = q.length - 1) < 0)
return null;
- int mask = q.length - 1;
- int i = locallyFifo ? base : (sp - 1);
- return q[i & mask];
+ int i = locallyFifo ? queueBase : (queueTop - 1);
+ return q[i & m];
}
+ // Support methods for ForkJoinPool
+
/**
- * Doubles queue array size. Transfers elements by emulating
- * steals (deqs) from old array and placing, oldest first, into
- * new array.
+ * Runs the given task, plus any local tasks until queue is empty
*/
- private void growQueue() {
- ForkJoinTask>[] oldQ = queue;
- int oldSize = oldQ.length;
- int newSize = oldSize << 1;
- if (newSize > MAXIMUM_QUEUE_CAPACITY)
- throw new RejectedExecutionException("Queue capacity exceeded");
- ForkJoinTask>[] newQ = queue = new ForkJoinTask>[newSize];
-
- int b = base;
- int bf = b + oldSize;
- int oldMask = oldSize - 1;
- int newMask = newSize - 1;
- do {
- int oldIndex = b & oldMask;
- ForkJoinTask> t = oldQ[oldIndex];
- if (t != null && !casSlotNull(oldQ, oldIndex, t))
- t = null;
- writeSlot(newQ, b & newMask, t);
- } while (++b != bf);
- pool.signalWork();
- }
-
- /**
- * Computes next value for random victim probe in scan(). Scans
- * don't require a very high quality generator, but also not a
- * crummy one. Marsaglia xor-shift is cheap and works well enough.
- * Note: This is manually inlined in scan().
- */
- private static final int xorShift(int r) {
- r ^= r << 13;
- r ^= r >>> 17;
- return r ^ (r << 5);
- }
-
- /**
- * Tries to steal a task from another worker. Starts at a random
- * index of workers array, and probes workers until finding one
- * with non-empty queue or finding that all are empty. It
- * randomly selects the first n probes. If these are empty, it
- * resorts to a circular sweep, which is necessary to accurately
- * set active status. (The circular sweep uses steps of
- * approximately half the array size plus 1, to avoid bias
- * stemming from leftmost packing of the array in ForkJoinPool.)
- *
- * This method must be both fast and quiet -- usually avoiding
- * memory accesses that could disrupt cache sharing etc other than
- * those needed to check for and take tasks (or to activate if not
- * already active). This accounts for, among other things,
- * updating random seed in place without storing it until exit.
- *
- * @return a task, or null if none found
- */
- private ForkJoinTask> scan() {
- ForkJoinPool p = pool;
- ForkJoinWorkerThread[] ws; // worker array
- int n; // upper bound of #workers
- if ((ws = p.workers) != null && (n = ws.length) > 1) {
- boolean canSteal = active; // shadow active status
- int r = seed; // extract seed once
- int mask = n - 1;
- int j = -n; // loop counter
- int k = r; // worker index, random if j < 0
- for (;;) {
- ForkJoinWorkerThread v = ws[k & mask];
- r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // inline xorshift
- ForkJoinTask>[] q; ForkJoinTask> t; int b, a;
- if (v != null && (b = v.base) != v.sp &&
- (q = v.queue) != null) {
- int i = (q.length - 1) & b;
- long u = (i << qShift) + qBase; // raw offset
- int pid = poolIndex;
- if ((t = q[i]) != null) {
- if (!canSteal && // inline p.tryIncrementActiveCount
- UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
- a = p.runState, a + 1))
- canSteal = active = true;
- if (canSteal && v.base == b++ &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- v.base = b;
- v.stealHint = pid;
- UNSAFE.putOrderedObject(this,
- currentStealOffset, t);
- seed = r;
- ++stealCount;
- return t;
- }
- }
- j = -n;
- k = r; // restart on contention
- }
- else if (++j <= 0)
- k = r;
- else if (j <= n)
- k += (n >>> 1) | 1;
- else
- break;
- }
- }
- return null;
- }
-
- // Run State management
-
- // status check methods used mainly by ForkJoinPool
- final boolean isRunning() { return runState == 0; }
- final boolean isTerminated() { return (runState & TERMINATED) != 0; }
- final boolean isSuspended() { return (runState & SUSPENDED) != 0; }
- final boolean isTrimmed() { return (runState & TRIMMED) != 0; }
-
- final boolean isTerminating() {
- if ((runState & TERMINATING) != 0)
- return true;
- if (pool.isAtLeastTerminating()) { // propagate pool state
- shutdown();
- return true;
- }
- return false;
- }
-
- /**
- * Sets state to TERMINATING. Does NOT unpark or interrupt
- * to wake up if currently blocked. Callers must do so if desired.
- */
- final void shutdown() {
+ final void execTask(ForkJoinTask> t) {
+ currentSteal = t;
for (;;) {
- int s = runState;
- if ((s & (TERMINATING|TERMINATED)) != 0)
- break;
- if ((s & SUSPENDED) != 0) { // kill and wakeup if suspended
- if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
- (s & ~SUSPENDED) |
- (TRIMMED|TERMINATING)))
- break;
- }
- else if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
- s | TERMINATING))
+ if (t != null)
+ t.doExec();
+ if (queueTop == queueBase)
break;
+ t = locallyFifo ? locallyDeqTask() : popTask();
}
- }
-
- /**
- * Sets state to TERMINATED. Called only by onTermination().
- */
- private void setTerminated() {
- int s;
- do {} while (!UNSAFE.compareAndSwapInt(this, runStateOffset,
- s = runState,
- s | (TERMINATING|TERMINATED)));
- }
-
- /**
- * If suspended, tries to set status to unsuspended.
- * Does NOT wake up if blocked.
- *
- * @return true if successful
- */
- final boolean tryUnsuspend() {
- int s;
- while (((s = runState) & SUSPENDED) != 0) {
- if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
- s & ~SUSPENDED))
- return true;
- }
- return false;
- }
-
- /**
- * Sets suspended status and blocks as spare until resumed
- * or shutdown.
- */
- final void suspendAsSpare() {
- for (;;) { // set suspended unless terminating
- int s = runState;
- if ((s & TERMINATING) != 0) { // must kill
- if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
- s | (TRIMMED | TERMINATING)))
- return;
- }
- else if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
- s | SUSPENDED))
- break;
- }
- ForkJoinPool p = pool;
- p.pushSpare(this);
- while ((runState & SUSPENDED) != 0) {
- if (p.tryAccumulateStealCount(this)) {
- interrupted(); // clear/ignore interrupts
- if ((runState & SUSPENDED) == 0)
- break;
- LockSupport.park(this);
- }
- }
- }
-
- // Misc support methods for ForkJoinPool
-
- /**
- * Returns an estimate of the number of tasks in the queue. Also
- * used by ForkJoinTask.
- */
- final int getQueueSize() {
- int n; // external calls must read base first
- return (n = -base + sp) <= 0 ? 0 : n;
+ ++stealCount;
+ currentSteal = null;
}
/**
@@ -899,17 +616,12 @@ public class ForkJoinWorkerThread extends Thread {
*/
final void cancelTasks() {
ForkJoinTask> cj = currentJoin; // try to cancel ongoing tasks
- if (cj != null && cj.status >= 0) {
+ if (cj != null && cj.status >= 0)
cj.cancelIgnoringExceptions();
- try {
- this.interrupt(); // awaken wait
- } catch (SecurityException ignore) {
- }
- }
ForkJoinTask> cs = currentSteal;
if (cs != null && cs.status >= 0)
cs.cancelIgnoringExceptions();
- while (base != sp) {
+ while (queueBase != queueTop) {
ForkJoinTask> t = deqTask();
if (t != null)
t.cancelIgnoringExceptions();
@@ -923,7 +635,7 @@ public class ForkJoinWorkerThread extends Thread {
*/
final int drainTasksTo(Collection super ForkJoinTask>> c) {
int n = 0;
- while (base != sp) {
+ while (queueBase != queueTop) {
ForkJoinTask> t = deqTask();
if (t != null) {
c.add(t);
@@ -935,21 +647,20 @@ public class ForkJoinWorkerThread extends Thread {
// Support methods for ForkJoinTask
+ /**
+ * Returns an estimate of the number of tasks in the queue.
+ */
+ final int getQueueSize() {
+ return queueTop - queueBase;
+ }
+
/**
* Gets and removes a local task.
*
* @return a task, if available
*/
final ForkJoinTask> pollLocalTask() {
- ForkJoinPool p = pool;
- while (sp != base) {
- int a; // inline p.tryIncrementActiveCount
- if (active ||
- (active = UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
- a = p.runState, a + 1)))
- return locallyFifo ? locallyDeqTask() : popTask();
- }
- return null;
+ return locallyFifo ? locallyDeqTask() : popTask();
}
/**
@@ -958,172 +669,205 @@ public class ForkJoinWorkerThread extends Thread {
* @return a task, if available
*/
final ForkJoinTask> pollTask() {
+ ForkJoinWorkerThread[] ws;
ForkJoinTask> t = pollLocalTask();
- if (t == null) {
- t = scan();
- // cannot retain/track/help steal
- UNSAFE.putOrderedObject(this, currentStealOffset, null);
+ if (t != null || (ws = pool.workers) == null)
+ return t;
+ int n = ws.length; // cheap version of FJP.scan
+ int steps = n << 1;
+ int r = nextSeed();
+ int i = 0;
+ while (i < steps) {
+ ForkJoinWorkerThread w = ws[(i++ + r) & (n - 1)];
+ if (w != null && w.queueBase != w.queueTop && w.queue != null) {
+ if ((t = w.deqTask()) != null)
+ return t;
+ i = 0;
+ }
}
- return t;
+ return null;
}
/**
- * Possibly runs some tasks and/or blocks, until task is done.
+ * The maximum stolen->joining link depth allowed in helpJoinTask,
+ * as well as the maximum number of retries (allowing on average
+ * one staleness retry per level) per attempt to instead try
+ * compensation. Depths for legitimate chains are unbounded, but
+ * we use a fixed constant to avoid (otherwise unchecked) cycles
+ * and bound staleness of traversal parameters at the expense of
+ * sometimes blocking when we could be helping.
+ */
+ private static final int MAX_HELP = 16;
+
+ /**
+ * Possibly runs some tasks and/or blocks, until joinMe is done.
*
* @param joinMe the task to join
- * @param timed true if use timed wait
- * @param nanos wait time if timed
+ * @return completion status on exit
*/
- final void joinTask(ForkJoinTask> joinMe, boolean timed, long nanos) {
- // currentJoin only written by this thread; only need ordered store
+ final int joinTask(ForkJoinTask> joinMe) {
ForkJoinTask> prevJoin = currentJoin;
- UNSAFE.putOrderedObject(this, currentJoinOffset, joinMe);
- pool.awaitJoin(joinMe, this, timed, nanos);
- UNSAFE.putOrderedObject(this, currentJoinOffset, prevJoin);
+ currentJoin = joinMe;
+ for (int s, retries = MAX_HELP;;) {
+ if ((s = joinMe.status) < 0) {
+ currentJoin = prevJoin;
+ return s;
+ }
+ if (retries > 0) {
+ if (queueTop != queueBase) {
+ if (!localHelpJoinTask(joinMe))
+ retries = 0; // cannot help
+ }
+ else if (retries == MAX_HELP >>> 1) {
+ --retries; // check uncommon case
+ if (tryDeqAndExec(joinMe) >= 0)
+ Thread.yield(); // for politeness
+ }
+ else
+ retries = helpJoinTask(joinMe)? MAX_HELP : retries - 1;
+ }
+ else {
+ retries = MAX_HELP; // restart if not done
+ pool.tryAwaitJoin(joinMe);
+ }
+ }
}
/**
- * Tries to locate and help perform tasks for a stealer of the
- * given task, or in turn one of its stealers. Traces
+ * If present, pops and executes the given task, or any other
+ * cancelled task
+ *
+ * @return false if any other non-cancelled task exists in local queue
+ */
+ private boolean localHelpJoinTask(ForkJoinTask> joinMe) {
+ int s, i; ForkJoinTask>[] q; ForkJoinTask> t;
+ if ((s = queueTop) != queueBase && (q = queue) != null &&
+ (i = (q.length - 1) & --s) >= 0 &&
+ (t = q[i]) != null) {
+ if (t != joinMe && t.status >= 0)
+ return false;
+ if (UNSAFE.compareAndSwapObject
+ (q, (i << ASHIFT) + ABASE, t, null)) {
+ queueTop = s; // or putOrderedInt
+ t.doExec();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tries to locate and execute tasks for a stealer of the given
+ * task, or in turn one of its stealers, Traces
* currentSteal->currentJoin links looking for a thread working on
* a descendant of the given task and with a non-empty queue to
- * steal back and execute tasks from.
- *
- * The implementation is very branchy to cope with potential
- * inconsistencies or loops encountering chains that are stale,
- * unknown, or of length greater than MAX_HELP_DEPTH links. All
- * of these cases are dealt with by just returning back to the
- * caller, who is expected to retry if other join mechanisms also
- * don't work out.
+ * steal back and execute tasks from. The implementation is very
+ * branchy to cope with potential inconsistencies or loops
+ * encountering chains that are stale, unknown, or of length
+ * greater than MAX_HELP links. All of these cases are dealt with
+ * by just retrying by caller.
*
* @param joinMe the task to join
- * @param running if false, then must update pool count upon
- * running a task
- * @return value of running on exit
+ * @param canSteal true if local queue is empty
+ * @return true if ran a task
*/
- final boolean helpJoinTask(ForkJoinTask> joinMe, boolean running) {
- /*
- * Initial checks to (1) abort if terminating; (2) clean out
- * old cancelled tasks from local queue; (3) if joinMe is next
- * task, run it; (4) omit scan if local queue nonempty (since
- * it may contain non-descendents of joinMe).
- */
- ForkJoinPool p = pool;
- for (;;) {
- ForkJoinTask>[] q;
- int s;
- if (joinMe.status < 0)
- return running;
- else if ((runState & TERMINATING) != 0) {
- joinMe.cancelIgnoringExceptions();
- return running;
- }
- else if ((s = sp) == base || (q = queue) == null)
- break; // queue empty
- else {
- int i = (q.length - 1) & --s;
- long u = (i << qShift) + qBase; // raw offset
- ForkJoinTask> t = q[i];
- if (t == null)
- break; // lost to a stealer
- else if (t != joinMe && t.status >= 0)
- return running; // cannot safely help
- else if ((running ||
- (running = p.tryIncrementRunningCount())) &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- sp = s; // putOrderedInt may encourage more timely write
- // UNSAFE.putOrderedInt(this, spOffset, s);
- t.quietlyExec();
- }
- }
- }
-
- int n; // worker array size
- ForkJoinWorkerThread[] ws = p.workers;
- if (ws != null && (n = ws.length) > 1) { // need at least 2 workers
- ForkJoinTask> task = joinMe; // base of chain
- ForkJoinWorkerThread thread = this; // thread with stolen task
-
- outer:for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length
+ private boolean helpJoinTask(ForkJoinTask> joinMe) {
+ boolean helped = false;
+ int m = pool.scanGuard & SMASK;
+ ForkJoinWorkerThread[] ws = pool.workers;
+ if (ws != null && ws.length > m && joinMe.status >= 0) {
+ int levels = MAX_HELP; // remaining chain length
+ ForkJoinTask> task = joinMe; // base of chain
+ outer:for (ForkJoinWorkerThread thread = this;;) {
// Try to find v, the stealer of task, by first using hint
- ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)];
+ ForkJoinWorkerThread v = ws[thread.stealHint & m];
if (v == null || v.currentSteal != task) {
- for (int j = 0; ; ++j) { // search array
- if (j < n) {
- ForkJoinTask> vs;
- if ((v = ws[j]) != null &&
- (vs = v.currentSteal) != null) {
- if (joinMe.status < 0)
- break outer;
- if (vs == task) {
- if (task.status < 0)
- break outer; // stale
- thread.stealHint = j;
- break; // save hint for next time
- }
- }
+ for (int j = 0; ;) { // search array
+ if ((v = ws[j]) != null && v.currentSteal == task) {
+ thread.stealHint = j;
+ break; // save hint for next time
}
- else
- break outer; // no stealer
+ if (++j > m)
+ break outer; // can't find stealer
}
}
-
// Try to help v, using specialized form of deqTask
for (;;) {
+ ForkJoinTask>[] q; int b, i;
if (joinMe.status < 0)
break outer;
- int b = v.base;
- ForkJoinTask>[] q = v.queue;
- if (b == v.sp || q == null)
- break; // empty
- int i = (q.length - 1) & b;
- long u = (i << qShift) + qBase;
+ if ((b = v.queueBase) == v.queueTop ||
+ (q = v.queue) == null ||
+ (i = (q.length-1) & b) < 0)
+ break; // empty
+ long u = (i << ASHIFT) + ABASE;
ForkJoinTask> t = q[i];
if (task.status < 0)
- break outer; // stale
- if (t != null &&
- (running ||
- (running = p.tryIncrementRunningCount())) &&
- v.base == b++ &&
+ break outer; // stale
+ if (t != null && v.queueBase == b &&
UNSAFE.compareAndSwapObject(q, u, t, null)) {
- if (t != joinMe && joinMe.status < 0) {
- UNSAFE.putObjectVolatile(q, u, t);
- break outer; // joinMe cancelled; back out
- }
- v.base = b;
- if (t.status >= 0) {
- ForkJoinTask> ps = currentSteal;
- int pid = poolIndex;
- v.stealHint = pid;
- UNSAFE.putOrderedObject(this,
- currentStealOffset, t);
- t.quietlyExec();
- UNSAFE.putOrderedObject(this,
- currentStealOffset, ps);
- }
- }
- else if ((runState & TERMINATING) != 0) {
- joinMe.cancelIgnoringExceptions();
- break outer;
+ v.queueBase = b + 1;
+ v.stealHint = poolIndex;
+ ForkJoinTask> ps = currentSteal;
+ currentSteal = t;
+ t.doExec();
+ currentSteal = ps;
+ helped = true;
}
}
-
// Try to descend to find v's stealer
ForkJoinTask> next = v.currentJoin;
- if (task.status < 0 || next == null || next == task ||
- joinMe.status < 0)
- break; // done, stale, dead-end, or cyclic
- task = next;
- thread = v;
+ if (--levels > 0 && task.status >= 0 &&
+ next != null && next != task) {
+ task = next;
+ thread = v;
+ }
+ else
+ break; // max levels, stale, dead-end, or cyclic
}
}
- return running;
+ return helped;
}
/**
- * Implements ForkJoinTask.getSurplusQueuedTaskCount().
- * Returns an estimate of the number of tasks, offset by a
- * function of number of idle workers.
+ * Performs an uncommon case for joinTask: If task t is at base of
+ * some workers queue, steals and executes it.
+ *
+ * @param t the task
+ * @return t's status
+ */
+ private int tryDeqAndExec(ForkJoinTask> t) {
+ int m = pool.scanGuard & SMASK;
+ ForkJoinWorkerThread[] ws = pool.workers;
+ if (ws != null && ws.length > m && t.status >= 0) {
+ for (int j = 0; j <= m; ++j) {
+ ForkJoinTask>[] q; int b, i;
+ ForkJoinWorkerThread v = ws[j];
+ if (v != null &&
+ (b = v.queueBase) != v.queueTop &&
+ (q = v.queue) != null &&
+ (i = (q.length - 1) & b) >= 0 &&
+ q[i] == t) {
+ long u = (i << ASHIFT) + ABASE;
+ if (v.queueBase == b &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ v.queueBase = b + 1;
+ v.stealHint = poolIndex;
+ ForkJoinTask> ps = currentSteal;
+ currentSteal = t;
+ t.doExec();
+ currentSteal = ps;
+ }
+ break;
+ }
+ }
+ }
+ return t.status;
+ }
+
+ /**
+ * Implements ForkJoinTask.getSurplusQueuedTaskCount(). Returns
+ * an estimate of the number of tasks, offset by a function of
+ * number of idle workers.
*
* This method provides a cheap heuristic guide for task
* partitioning when programmers, frameworks, tools, or languages
@@ -1159,82 +903,96 @@ public class ForkJoinWorkerThread extends Thread {
* When all threads are active, it is on average OK to estimate
* surplus strictly locally. In steady-state, if one thread is
* maintaining say 2 surplus tasks, then so are others. So we can
- * just use estimated queue length (although note that (sp - base)
- * can be an overestimate because of stealers lagging increments
- * of base). However, this strategy alone leads to serious
- * mis-estimates in some non-steady-state conditions (ramp-up,
- * ramp-down, other stalls). We can detect many of these by
- * further considering the number of "idle" threads, that are
+ * just use estimated queue length (although note that (queueTop -
+ * queueBase) can be an overestimate because of stealers lagging
+ * increments of queueBase). However, this strategy alone leads
+ * to serious mis-estimates in some non-steady-state conditions
+ * (ramp-up, ramp-down, other stalls). We can detect many of these
+ * by further considering the number of "idle" threads, that are
* known to have zero queued tasks, so compensate by a factor of
* (#idle/#active) threads.
*/
final int getEstimatedSurplusTaskCount() {
- return sp - base - pool.idlePerActive();
+ return queueTop - queueBase - pool.idlePerActive();
}
/**
- * Runs tasks until {@code pool.isQuiescent()}.
+ * Runs tasks until {@code pool.isQuiescent()}. We piggyback on
+ * pool's active count ctl maintenance, but rather than blocking
+ * when tasks cannot be found, we rescan until all others cannot
+ * find tasks either. The bracketing by pool quiescerCounts
+ * updates suppresses pool auto-shutdown mechanics that could
+ * otherwise prematurely terminate the pool because all threads
+ * appear to be inactive.
*/
final void helpQuiescePool() {
+ boolean active = true;
ForkJoinTask> ps = currentSteal; // to restore below
+ ForkJoinPool p = pool;
+ p.addQuiescerCount(1);
for (;;) {
- ForkJoinTask> t = pollLocalTask();
- if (t != null || (t = scan()) != null)
- t.quietlyExec();
+ ForkJoinWorkerThread[] ws = p.workers;
+ ForkJoinWorkerThread v = null;
+ int n;
+ if (queueTop != queueBase)
+ v = this;
+ else if (ws != null && (n = ws.length) > 1) {
+ ForkJoinWorkerThread w;
+ int r = nextSeed(); // cheap version of FJP.scan
+ int steps = n << 1;
+ for (int i = 0; i < steps; ++i) {
+ if ((w = ws[(i + r) & (n - 1)]) != null &&
+ w.queueBase != w.queueTop) {
+ v = w;
+ break;
+ }
+ }
+ }
+ if (v != null) {
+ ForkJoinTask> t;
+ if (!active) {
+ active = true;
+ p.addActiveCount(1);
+ }
+ if ((t = (v != this) ? v.deqTask() :
+ locallyFifo? locallyDeqTask() : popTask()) != null) {
+ currentSteal = t;
+ t.doExec();
+ currentSteal = ps;
+ }
+ }
else {
- ForkJoinPool p = pool;
- int a; // to inline CASes
if (active) {
- if (!UNSAFE.compareAndSwapInt
- (p, poolRunStateOffset, a = p.runState, a - 1))
- continue; // retry later
- active = false; // inactivate
- UNSAFE.putOrderedObject(this, currentStealOffset, ps);
+ active = false;
+ p.addActiveCount(-1);
}
if (p.isQuiescent()) {
- active = true; // re-activate
- do {} while (!UNSAFE.compareAndSwapInt
- (p, poolRunStateOffset, a = p.runState, a+1));
- return;
+ p.addActiveCount(1);
+ p.addQuiescerCount(-1);
+ break;
}
}
}
}
// Unsafe mechanics
-
- private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
- private static final long spOffset =
- objectFieldOffset("sp", ForkJoinWorkerThread.class);
- private static final long runStateOffset =
- objectFieldOffset("runState", ForkJoinWorkerThread.class);
- private static final long currentJoinOffset =
- objectFieldOffset("currentJoin", ForkJoinWorkerThread.class);
- private static final long currentStealOffset =
- objectFieldOffset("currentSteal", ForkJoinWorkerThread.class);
- private static final long qBase =
- UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
- private static final long poolRunStateOffset = // to inline CAS
- objectFieldOffset("runState", ForkJoinPool.class);
-
- private static final int qShift;
+ private static final sun.misc.Unsafe UNSAFE;
+ private static final long ABASE;
+ private static final int ASHIFT;
static {
- int s = UNSAFE.arrayIndexScale(ForkJoinTask[].class);
+ int s;
+ try {
+ UNSAFE = sun.misc.Unsafe.getUnsafe();
+ Class a = ForkJoinTask[].class;
+ ABASE = UNSAFE.arrayBaseOffset(a);
+ s = UNSAFE.arrayIndexScale(a);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
if ((s & (s-1)) != 0)
throw new Error("data type scale not a power of two");
- qShift = 31 - Integer.numberOfLeadingZeros(s);
- MAXIMUM_QUEUE_CAPACITY = 1 << (31 - qShift);
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
}
- private static long objectFieldOffset(String field, Class> klazz) {
- try {
- return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
- } catch (NoSuchFieldException e) {
- // Convert Exception to corresponding Error
- NoSuchFieldError error = new NoSuchFieldError(field);
- error.initCause(e);
- throw error;
- }
- }
}
diff --git a/jdk/src/share/classes/javax/swing/JOptionPane.java b/jdk/src/share/classes/javax/swing/JOptionPane.java
index 66154cf39b5..307d834b4e6 100644
--- a/jdk/src/share/classes/javax/swing/JOptionPane.java
+++ b/jdk/src/share/classes/javax/swing/JOptionPane.java
@@ -987,11 +987,33 @@ public class JOptionPane extends JComponent implements Accessible
}
dialog.pack();
dialog.setLocationRelativeTo(parentComponent);
+
+ final PropertyChangeListener listener = new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ // Let the defaultCloseOperation handle the closing
+ // if the user closed the window without selecting a button
+ // (newValue = null in that case). Otherwise, close the dialog.
+ if (dialog.isVisible() && event.getSource() == JOptionPane.this &&
+ (event.getPropertyName().equals(VALUE_PROPERTY) ||
+ event.getPropertyName().equals(INPUT_VALUE_PROPERTY)) &&
+ event.getNewValue() != null &&
+ event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
+ dialog.setVisible(false);
+ }
+ }
+ };
+
WindowAdapter adapter = new WindowAdapter() {
private boolean gotFocus = false;
public void windowClosing(WindowEvent we) {
setValue(null);
}
+
+ public void windowClosed(WindowEvent e) {
+ removePropertyChangeListener(listener);
+ dialog.getContentPane().removeAll();
+ }
+
public void windowGainedFocus(WindowEvent we) {
// Once window gets focus, set initial focus
if (!gotFocus) {
@@ -1008,20 +1030,8 @@ public class JOptionPane extends JComponent implements Accessible
setValue(JOptionPane.UNINITIALIZED_VALUE);
}
});
- addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent event) {
- // Let the defaultCloseOperation handle the closing
- // if the user closed the window without selecting a button
- // (newValue = null in that case). Otherwise, close the dialog.
- if (dialog.isVisible() && event.getSource() == JOptionPane.this &&
- (event.getPropertyName().equals(VALUE_PROPERTY) ||
- event.getPropertyName().equals(INPUT_VALUE_PROPERTY)) &&
- event.getNewValue() != null &&
- event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
- dialog.setVisible(false);
- }
- }
- });
+
+ addPropertyChangeListener(listener);
}
diff --git a/jdk/src/share/classes/javax/swing/Timer.java b/jdk/src/share/classes/javax/swing/Timer.java
index 9e98d5f920e..c6c80baeda9 100644
--- a/jdk/src/share/classes/javax/swing/Timer.java
+++ b/jdk/src/share/classes/javax/swing/Timer.java
@@ -35,6 +35,10 @@ import java.util.concurrent.locks.*;
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
+import java.io.*;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.swing.event.EventListenerList;
@@ -208,6 +212,22 @@ public class Timer implements Serializable
}
}
+ /*
+ * The timer's AccessControlContext.
+ */
+ private transient volatile AccessControlContext acc =
+ AccessController.getContext();
+
+ /**
+ * Returns the acc this timer was constructed with.
+ */
+ final AccessControlContext getAccessControlContext() {
+ if (acc == null) {
+ throw new SecurityException(
+ "Timer is missing AccessControlContext");
+ }
+ return acc;
+ }
/**
* DoPostEvent is a runnable class that fires actionEvents to
@@ -587,8 +607,13 @@ public class Timer implements Serializable
void post() {
- if (notify.compareAndSet(false, true) || !coalesce) {
- SwingUtilities.invokeLater(doPostEvent);
+ if (notify.compareAndSet(false, true) || !coalesce) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Void run() {
+ SwingUtilities.invokeLater(doPostEvent);
+ return null;
+ }
+ }, getAccessControlContext());
}
}
@@ -596,6 +621,13 @@ public class Timer implements Serializable
return lock;
}
+ private void readObject(ObjectInputStream in)
+ throws ClassNotFoundException, IOException
+ {
+ this.acc = AccessController.getContext();
+ in.defaultReadObject();
+ }
+
/*
* We have to use readResolve because we can not initialize final
* fields for deserialized object otherwise
diff --git a/jdk/src/share/classes/javax/swing/TransferHandler.java b/jdk/src/share/classes/javax/swing/TransferHandler.java
index eb7f8d1a644..dd54b259eef 100644
--- a/jdk/src/share/classes/javax/swing/TransferHandler.java
+++ b/jdk/src/share/classes/javax/swing/TransferHandler.java
@@ -42,6 +42,16 @@ import sun.awt.AppContext;
import sun.swing.*;
import sun.awt.SunToolkit;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.security.AccessControlContext;
+import java.security.ProtectionDomain;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaSecurityAccess;
+
+import sun.awt.AWTAccessor;
+
/**
* This class is used to handle the transfer of a Transferable
* to and from Swing components. The Transferable is used to
@@ -1686,7 +1696,37 @@ public class TransferHandler implements Serializable {
return true;
}
- public void actionPerformed(ActionEvent e) {
+ private static final JavaSecurityAccess javaSecurityAccess =
+ SharedSecrets.getJavaSecurityAccess();
+
+ public void actionPerformed(final ActionEvent e) {
+ final Object src = e.getSource();
+
+ final PrivilegedAction action = new PrivilegedAction() {
+ public Void run() {
+ actionPerformedImpl(e);
+ return null;
+ }
+ };
+
+ final AccessControlContext stack = AccessController.getContext();
+ final AccessControlContext srcAcc = AWTAccessor.getComponentAccessor().getAccessControlContext((Component)src);
+ final AccessControlContext eventAcc = AWTAccessor.getAWTEventAccessor().getAccessControlContext(e);
+
+ if (srcAcc == null) {
+ javaSecurityAccess.doIntersectionPrivilege(action, stack, eventAcc);
+ } else {
+ javaSecurityAccess.doIntersectionPrivilege(
+ new PrivilegedAction() {
+ public Void run() {
+ javaSecurityAccess.doIntersectionPrivilege(action, eventAcc);
+ return null;
+ }
+ }, stack, srcAcc);
+ }
+ }
+
+ private void actionPerformedImpl(ActionEvent e) {
Object src = e.getSource();
if (src instanceof JComponent) {
JComponent c = (JComponent) src;
diff --git a/jdk/src/share/classes/org/relaxng/datatype/Datatype.java b/jdk/src/share/classes/org/relaxng/datatype/Datatype.java
deleted file mode 100644
index f1b4d8df244..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/Datatype.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * Datatype object.
- *
- * This object has the following functionality:
- *
- *
- * functionality to identify a class of character sequences. This is
- * done through the isValid method.
- *
- * functionality to produce a "value object" from a character sequence and
- * context information.
- *
- * functionality to test the equality of two value objects.
- *
- *
- * This interface also defines the createStreamingValidator method,
- * which is intended to efficiently support the validation of
- * large character sequences.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface Datatype {
-
- /**
- * Checks if the specified 'literal' matches this Datatype
- * with respect to the current context.
- *
- * @param literal
- * the lexical representation to be checked.
- * @param context
- * If this datatype is context-dependent
- * (i.e. the {@link #isContextDependent} method returns true),
- * then the caller must provide a non-null valid context object.
- * Otherwise, the caller can pass null.
- *
- * @return
- * true if the 'literal' is a member of this Datatype;
- * false if it's not a member of this Datatype.
- */
- boolean isValid( String literal, ValidationContext context );
-
- /**
- * Similar to the isValid method but throws an exception with diagnosis
- * in case of errors.
- *
- *
- * If the specified 'literal' is a valid lexical representation for this
- * datatype, then this method must return without throwing any exception.
- * If not, the callee must throw an exception (with diagnosis message,
- * if possible.)
- *
- *
- * The application can use this method to provide detailed error message
- * to users. This method is kept separate from the isValid method to
- * achieve higher performance during normal validation.
- *
- * @exception DatatypeException
- * If the given literal is invalid, then this exception is thrown.
- * If the callee supports error diagnosis, then the exception should
- * contain a diagnosis message.
- */
- void checkValid( String literal, ValidationContext context )
- throws DatatypeException;
-
- /**
- * Creates an instance of a streaming validator for this type.
- *
- *
- * By using streaming validators instead of the isValid method,
- * the caller can avoid keeping the entire string, which is
- * sometimes quite big, in memory.
- *
- * @param context
- * If this datatype is context-dependent
- * (i.e. the {@link #isContextDependent} method returns true),
- * then the caller must provide a non-null valid context object.
- * Otherwise, the caller can pass null.
- * The callee may keep a reference to this context object
- * only while the returned streaming validator is being used.
- */
- DatatypeStreamingValidator createStreamingValidator( ValidationContext context );
-
- /**
- * Converts lexcial value and the current context to the corresponding
- * value object.
- *
- *
- * The caller cannot generally assume that the value object is
- * a meaningful Java object. For example, the caller cannot expect
- * this method to return java.lang.Number type for
- * the "integer" type of XML Schema Part 2.
- *
- *
- * Also, the caller cannot assume that the equals method and
- * the hashCode method of the value object are consistent with
- * the semantics of the datatype. For that purpose, the sameValue
- * method and the valueHashCode method have to be used. Note that
- * this means you cannot use classes like
- * java.util.Hashtable to store the value objects.
- *
- *
- * The returned value object should be used solely for the sameValue
- * and valueHashCode methods.
- *
- * @param context
- * If this datatype is context-dependent
- * (when the {@link #isContextDependent} method returns true),
- * then the caller must provide a non-null valid context object.
- * Otherwise, the caller can pass null.
- *
- * @return null
- * when the given lexical value is not a valid lexical
- * value for this type.
- */
- Object createValue( String literal, ValidationContext context );
-
- /**
- * Tests the equality of two value objects which were originally
- * created by the createValue method of this object.
- *
- * The behavior is undefined if objects not created by this type
- * are passed. It is the caller's responsibility to ensure that
- * value objects belong to this type.
- *
- * @return
- * true if two value objects are considered equal according to
- * the definition of this datatype; false if otherwise.
- */
- boolean sameValue( Object value1, Object value2 );
-
-
- /**
- * Computes the hash code for a value object,
- * which is consistent with the sameValue method.
- *
- * @return
- * hash code for the specified value object.
- */
- int valueHashCode( Object value );
-
-
-
-
- /**
- * Indicates that the datatype doesn't have ID/IDREF semantics.
- *
- * This value is one of the possible return values of the
- * {@link #getIdType} method.
- */
- public static final int ID_TYPE_NULL = 0;
-
- /**
- * Indicates that RELAX NG compatibility processors should
- * treat this datatype as having ID semantics.
- *
- * This value is one of the possible return values of the
- * {@link #getIdType} method.
- */
- public static final int ID_TYPE_ID = 1;
-
- /**
- * Indicates that RELAX NG compatibility processors should
- * treat this datatype as having IDREF semantics.
- *
- * This value is one of the possible return values of the
- * {@link #getIdType} method.
- */
- public static final int ID_TYPE_IDREF = 2;
-
- /**
- * Indicates that RELAX NG compatibility processors should
- * treat this datatype as having IDREFS semantics.
- *
- * This value is one of the possible return values of the
- * {@link #getIdType} method.
- */
- public static final int ID_TYPE_IDREFS = 3;
-
- /**
- * Checks if the ID/IDREF semantics is associated with this
- * datatype.
- *
- *
- * This method is introduced to support the RELAX NG DTD
- * compatibility spec. (Of course it's always free to use
- * this method for other purposes.)
- *
- *
- * If you are implementing a datatype library and have no idea about
- * the "RELAX NG DTD compatibility" thing, just return
- * ID_TYPE_NULL is fine.
- *
- * @return
- * If this datatype doesn't have any ID/IDREF semantics,
- * it returns {@link #ID_TYPE_NULL}. If it has such a semantics
- * (for example, XSD:ID, XSD:IDREF and comp:ID type), then
- * it returns {@link #ID_TYPE_ID}, {@link #ID_TYPE_IDREF} or
- * {@link #ID_TYPE_IDREFS}.
- */
- public int getIdType();
-
-
- /**
- * Checks if this datatype may need a context object for
- * the validation.
- *
- *
- * The callee must return true even when the context
- * is not always necessary. (For example, the "QName" type
- * doesn't need a context object when validating unprefixed
- * string. But nonetheless QName must return true.)
- *
- *
- * XSD's string and short types
- * are examples of context-independent datatypes.
- * Its QName and ENTITY types
- * are examples of context-dependent datatypes.
- *
- *
- * When a datatype is context-independent, then
- * the {@link #isValid} method, the {@link #checkValid} method,
- * the {@link #createStreamingValidator} method and
- * the {@link #createValue} method can be called without
- * providing a context object.
- *
- * @return
- * true if this datatype is context-dependent
- * (it needs a context object sometimes);
- *
- * false if this datatype is context-in dependent
- * (it never needs a context object).
- */
- public boolean isContextDependent();
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/DatatypeBuilder.java b/jdk/src/share/classes/org/relaxng/datatype/DatatypeBuilder.java
deleted file mode 100644
index ea15f33cea2..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/DatatypeBuilder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * Creates a user-defined type by adding parameters to
- * the pre-defined type.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface DatatypeBuilder {
-
- /**
- * Adds a new parameter.
- *
- * @param name
- * The name of the parameter to be added.
- * @param strValue
- * The raw value of the parameter. Caller may not normalize
- * this value because any white space is potentially significant.
- * @param context
- * The context information which can be used by the callee to
- * acquire additional information. This context object is
- * valid only during this method call. The callee may not
- * keep a reference to this object.
- * @exception DatatypeException
- * When the given parameter is inappropriate for some reason.
- * The callee is responsible to recover from this error.
- * That is, the object should behave as if no such error
- * was occured.
- */
- void addParameter( String name, String strValue, ValidationContext context )
- throws DatatypeException;
-
- /**
- * Derives a new Datatype from a Datatype by parameters that
- * were already set through the addParameter method.
- *
- * @exception DatatypeException
- * DatatypeException must be thrown if the derivation is
- * somehow invalid. For example, a required parameter is missing,
- * etc. The exception should contain a diagnosis message
- * if possible.
- */
- Datatype createDatatype() throws DatatypeException;
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibrary.java b/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibrary.java
deleted file mode 100644
index f3f790d91e2..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibrary.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * A Datatype library
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface DatatypeLibrary {
-
- /**
- * Creates a new instance of DatatypeBuilder.
- *
- * The callee should throw a DatatypeException in case of an error.
- *
- * @param baseTypeLocalName
- * The local name of the base type.
- *
- * @return
- * A non-null valid datatype object.
- */
- DatatypeBuilder createDatatypeBuilder( String baseTypeLocalName )
- throws DatatypeException;
-
- /**
- * Gets or creates a pre-defined type.
- *
- * This is just a short-cut of
- * createDatatypeBuilder(typeLocalName).createDatatype();
- *
- * The callee should throw a DatatypeException in case of an error.
- *
- * @return
- * A non-null valid datatype object.
- */
- Datatype createDatatype( String typeLocalName ) throws DatatypeException;
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibraryFactory.java b/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibraryFactory.java
deleted file mode 100644
index e406c078894..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/DatatypeLibraryFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * Factory class for the DatatypeLibrary class.
- *
- *
- * The datatype library should provide the implementation of
- * this interface if it wants to be found by the schema processors.
- * The implementor also have to place a file in your jar file.
- * See the reference datatype library implementation for detail.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface DatatypeLibraryFactory
-{
- /**
- * Creates a new instance of a DatatypeLibrary that supports
- * the specified namespace URI.
- *
- * @return
- * null if the specified namespace URI is not
- * supported.
- */
- DatatypeLibrary createDatatypeLibrary( String namespaceURI );
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/DatatypeStreamingValidator.java b/jdk/src/share/classes/org/relaxng/datatype/DatatypeStreamingValidator.java
deleted file mode 100644
index 56663923278..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/DatatypeStreamingValidator.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * Datatype streaming validator.
- *
- *
- * The streaming validator is an optional feature that is useful for
- * certain Datatypes. It allows the caller to incrementally provide
- * the literal.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface DatatypeStreamingValidator {
-
- /**
- * Passes an additional fragment of the literal.
- *
- *
- * The application can call this method several times, then call
- * the isValid method (or the checkValid method) to check the validity
- * of the accumulated characters.
- */
- void addCharacters( char[] buf, int start, int len );
-
- /**
- * Tells if the accumulated literal is valid with respect to
- * the underlying Datatype.
- *
- * @return
- * True if it is valid. False if otherwise.
- */
- boolean isValid();
-
- /**
- * Similar to the isValid method, but this method throws
- * Exception (with possibly diagnostic information), instead of
- * returning false.
- *
- * @exception DatatypeException
- * If the callee supports the diagnosis and the accumulated
- * literal is invalid, then this exception that possibly
- * contains diagnosis information is thrown.
- */
- void checkValid() throws DatatypeException;
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/ValidationContext.java b/jdk/src/share/classes/org/relaxng/datatype/ValidationContext.java
deleted file mode 100644
index 8e37b0ee6a5..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/ValidationContext.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype;
-
-/**
- * An interface that must be implemented by caller to
- * provide context information that is necessary to
- * perform validation of some Datatypes.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
- */
-public interface ValidationContext {
-
- /**
- * Resolves a namespace prefix to the corresponding namespace URI.
- *
- * This method is used for validating the QName type, for example.
- *
- *
- * If the prefix is "" (empty string), it indicates
- * an unprefixed value. The callee
- * should resolve it as for an unprefixed
- * element, rather than for an unprefixed attribute.
- *
- *
- * If the prefix is "xml", then the callee must resolve
- * this prefix into "http://www.w3.org/XML/1998/namespace",
- * as defined in the XML Namespaces Recommendation.
- *
- * @return
- * namespace URI of this prefix.
- * If the specified prefix is not declared,
- * the implementation must return null.
- */
- String resolveNamespacePrefix( String prefix );
-
- /**
- * Returns the base URI of the context. The null string may be returned
- * if no base URI is known.
- */
- String getBaseUri();
-
- /**
- * Checks if an unparsed entity is declared with the
- * specified name.
- *
- * @return
- * true
- * if the DTD has an unparsed entity declaration for
- * the specified name.
- * false
- * otherwise.
- */
- boolean isUnparsedEntity( String entityName );
-
- /**
- * Checks if a notation is declared with the
- * specified name.
- *
- * @return
- * true
- * if the DTD has a notation declaration for the specified name.
- * false
- * otherwise.
- */
- boolean isNotation( String notationName );
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java b/jdk/src/share/classes/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java
deleted file mode 100644
index a3091b08780..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
- * Copyright (c) 2001, Thai Open Source Software Center Ltd
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of the Thai Open Source Software Center Ltd nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.relaxng.datatype.helpers;
-
-import org.relaxng.datatype.DatatypeLibraryFactory;
-import org.relaxng.datatype.DatatypeLibrary;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-import java.util.Vector;
-import java.io.Reader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-
-/**
- * Discovers the datatype library implementation from the classpath.
- *
- *
- * The call of the createDatatypeLibrary method finds an implementation
- * from a given datatype library URI at run-time.
- */
-public class DatatypeLibraryLoader implements DatatypeLibraryFactory {
- private final Service service = new Service(DatatypeLibraryFactory.class);
-
- public DatatypeLibrary createDatatypeLibrary(String uri) {
- for (Enumeration e = service.getProviders();
- e.hasMoreElements();) {
- DatatypeLibraryFactory factory
- = (DatatypeLibraryFactory)e.nextElement();
- DatatypeLibrary library = factory.createDatatypeLibrary(uri);
- if (library != null)
- return library;
- }
- return null;
- }
-
- private static class Service {
- private final Class serviceClass;
- private final Enumeration configFiles;
- private Enumeration classNames = null;
- private final Vector providers = new Vector();
- private Loader loader;
-
- private class ProviderEnumeration implements Enumeration {
- private int nextIndex = 0;
-
- public boolean hasMoreElements() {
- return nextIndex < providers.size() || moreProviders();
- }
-
- public Object nextElement() {
- try {
- return providers.elementAt(nextIndex++);
- }
- catch (ArrayIndexOutOfBoundsException e) {
- throw new NoSuchElementException();
- }
- }
- }
-
- private static class Singleton implements Enumeration {
- private Object obj;
- private Singleton(Object obj) {
- this.obj = obj;
- }
-
- public boolean hasMoreElements() {
- return obj != null;
- }
-
- public Object nextElement() {
- if (obj == null)
- throw new NoSuchElementException();
- Object tem = obj;
- obj = null;
- return tem;
- }
- }
-
- // JDK 1.1
- private static class Loader {
- Enumeration getResources(String resName) {
- ClassLoader cl = Loader.class.getClassLoader();
- URL url;
- if (cl == null)
- url = ClassLoader.getSystemResource(resName);
- else
- url = cl.getResource(resName);
- return new Singleton(url);
- }
-
- Class loadClass(String name) throws ClassNotFoundException {
- return Class.forName(name);
- }
- }
-
- // JDK 1.2+
- private static class Loader2 extends Loader {
- private ClassLoader cl;
-
- Loader2() {
- cl = Loader2.class.getClassLoader();
- // If the thread context class loader has the class loader
- // of this class as an ancestor, use the thread context class
- // loader. Otherwise, the thread context class loader
- // probably hasn't been set up properly, so don't use it.
- ClassLoader clt = Thread.currentThread().getContextClassLoader();
- for (ClassLoader tem = clt; tem != null; tem = tem.getParent())
- if (tem == cl) {
- cl = clt;
- break;
- }
- }
-
- Enumeration getResources(String resName) {
- try {
- return cl.getResources(resName);
-
- }
- catch (IOException e) {
- return new Singleton(null);
- }
- }
-
- Class loadClass(String name) throws ClassNotFoundException {
- return Class.forName(name, true, cl);
- }
- }
-
- public Service(Class cls) {
- try {
- loader = new Loader2();
- }
- catch (NoSuchMethodError e) {
- loader = new Loader();
- }
- serviceClass = cls;
- String resName = "META-INF/services/" + serviceClass.getName();
- configFiles = loader.getResources(resName);
- }
-
- public Enumeration getProviders() {
- return new ProviderEnumeration();
- }
-
- synchronized private boolean moreProviders() {
- for (;;) {
- while (classNames == null) {
- if (!configFiles.hasMoreElements())
- return false;
- classNames = parseConfigFile((URL)configFiles.nextElement());
- }
- while (classNames.hasMoreElements()) {
- String className = (String)classNames.nextElement();
- try {
- Class cls = loader.loadClass(className);
- Object obj = cls.newInstance();
- if (serviceClass.isInstance(obj)) {
- providers.addElement(obj);
- return true;
- }
- }
- catch (ClassNotFoundException e) { }
- catch (InstantiationException e) { }
- catch (IllegalAccessException e) { }
- catch (LinkageError e) { }
- }
- classNames = null;
- }
- }
-
- private static final int START = 0;
- private static final int IN_NAME = 1;
- private static final int IN_COMMENT = 2;
-
- private static Enumeration parseConfigFile(URL url) {
- try {
- InputStream in = url.openStream();
- Reader r;
- try {
- r = new InputStreamReader(in, "UTF-8");
- }
- catch (UnsupportedEncodingException e) {
- r = new InputStreamReader(in, "UTF8");
- }
- r = new BufferedReader(r);
- Vector tokens = new Vector();
- StringBuffer tokenBuf = new StringBuffer();
- int state = START;
- for (;;) {
- int n = r.read();
- if (n < 0)
- break;
- char c = (char)n;
- switch (c) {
- case '\r':
- case '\n':
- state = START;
- break;
- case ' ':
- case '\t':
- break;
- case '#':
- state = IN_COMMENT;
- break;
- default:
- if (state != IN_COMMENT) {
- state = IN_NAME;
- tokenBuf.append(c);
- }
- break;
- }
- if (tokenBuf.length() != 0 && state != IN_NAME) {
- tokens.addElement(tokenBuf.toString());
- tokenBuf.setLength(0);
- }
- }
- if (tokenBuf.length() != 0)
- tokens.addElement(tokenBuf.toString());
- return tokens.elements();
- }
- catch (IOException e) {
- return null;
- }
- }
- }
-
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/helpers/ParameterlessDatatypeBuilder.java b/jdk/src/share/classes/org/relaxng/datatype/helpers/ParameterlessDatatypeBuilder.java
deleted file mode 100644
index 8a5efb8b2dd..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/helpers/ParameterlessDatatypeBuilder.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype.helpers;
-
-import org.relaxng.datatype.*;
-
-/**
- * Dummy implementation of {@link DatatypeBuilder}.
- *
- * This implementation can be used for Datatypes which have no parameters.
- * Any attempt to add parameters will be rejected.
- *
- *
- * Typical usage would be:
- *
- * class MyDatatypeLibrary implements DatatypeLibrary {
- * ....
- * DatatypeBuilder createDatatypeBuilder( String typeName ) {
- * return new ParameterleessDatatypeBuilder(createDatatype(typeName));
- * }
- * ....
- * }
- *
- *
- * @author Kohsuke KAWAGUCHI
- */
-public final class ParameterlessDatatypeBuilder implements DatatypeBuilder {
-
- /** This type object is returned for the derive method. */
- private final Datatype baseType;
-
- public ParameterlessDatatypeBuilder( Datatype baseType ) {
- this.baseType = baseType;
- }
-
- public void addParameter( String name, String strValue, ValidationContext context )
- throws DatatypeException {
- throw new DatatypeException();
- }
-
- public Datatype createDatatype() throws DatatypeException {
- return baseType;
- }
-}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/helpers/StreamingValidatorImpl.java b/jdk/src/share/classes/org/relaxng/datatype/helpers/StreamingValidatorImpl.java
deleted file mode 100644
index 5f7cc79e967..00000000000
--- a/jdk/src/share/classes/org/relaxng/datatype/helpers/StreamingValidatorImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2005, 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 org.relaxng.datatype.helpers;
-
-import org.relaxng.datatype.*;
-
-/**
- * Dummy implementation of {@link DatatypeStreamingValidator}.
- *
- *
- * This implementation can be used as a quick hack when the performance
- * of streaming validation is not important. And this implementation
- * also shows you how to implement the DatatypeStreamingValidator interface.
- *
- *
- * Typical usage would be:
- *
- * class MyDatatype implements Datatype {
- * ....
- * public DatatypeStreamingValidator createStreamingValidator( ValidationContext context ) {
- * return new StreamingValidatorImpl(this,context);
- * }
- * ....
- * }
- *
- *
- * @author Kohsuke KAWAGUCHI
- */
-public final class StreamingValidatorImpl implements DatatypeStreamingValidator {
-
- /** This buffer accumulates characters. */
- private final StringBuffer buffer = new StringBuffer();
-
- /** Datatype obejct that creates this streaming validator. */
- private final Datatype baseType;
-
- /** The current context. */
- private final ValidationContext context;
-
- public void addCharacters( char[] buf, int start, int len ) {
- // append characters to the current buffer.
- buffer.append(buf,start,len);
- }
-
- public boolean isValid() {
- return baseType.isValid(buffer.toString(),context);
- }
-
- public void checkValid() throws DatatypeException {
- baseType.checkValid(buffer.toString(),context);
- }
-
- public StreamingValidatorImpl( Datatype baseType, ValidationContext context ) {
- this.baseType = baseType;
- this.context = context;
- }
-}
diff --git a/jdk/src/share/classes/overview-core.html b/jdk/src/share/classes/overview-core.html
index 86f33fe6ce9..c4b518c57b8 100644
--- a/jdk/src/share/classes/overview-core.html
+++ b/jdk/src/share/classes/overview-core.html
@@ -33,7 +33,7 @@ questions.
-This document is the API specification for version 6 of the Java™
+This document is the API specification for the Java™
Platform, Standard Edition.
diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java
index 0e38de6df6f..b88531dfcd2 100644
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java
@@ -33,6 +33,9 @@ import java.awt.image.BufferedImage;
import sun.misc.Unsafe;
import java.awt.peer.ComponentPeer;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+
/**
* The AWTAccessor utility class.
* The main purpose of this class is to enable accessing
@@ -221,6 +224,13 @@ public final class AWTAccessor {
* Processes events occurring on this component.
*/
void processEvent(Component comp, AWTEvent e);
+
+
+ /*
+ * Returns the acc this component was constructed with.
+ */
+ AccessControlContext getAccessControlContext(Component comp);
+
}
/*
@@ -323,6 +333,13 @@ public final class AWTAccessor {
* Indicates whether this AWTEvent was generated by the system.
*/
boolean isSystemGenerated(AWTEvent ev);
+
+
+ /*
+ * Returns the acc this event was constructed with.
+ */
+ AccessControlContext getAccessControlContext(AWTEvent ev);
+
}
public interface InputEventAccessor {
diff --git a/jdk/src/share/classes/sun/dyn/Access.java b/jdk/src/share/classes/sun/dyn/Access.java
deleted file mode 100644
index 931303b03b6..00000000000
--- a/jdk/src/share/classes/sun/dyn/Access.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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 sun.dyn;
-
-import sun.reflect.Reflection;
-
-/**
- * Access control to this package.
- * Classes in other packages can attempt to acquire the access token,
- * but will fail if they are not recognized as friends.
- * Certain methods in this package, although public, require a non-null
- * access token in order to proceed; they act like package-private methods.
- * @author jrose
- */
-
-public class Access {
-
- private Access() { }
-
- /**
- * The heart of this pattern: The list of classes which are
- * permitted to acquire the access token, and become honorary
- * members of this package.
- */
- private static final String[] FRIENDS = {
- "java.dyn.", "sun.dyn."
- };
-
- /**
- * The following object is NOT public. That's the point of the pattern.
- * It is package-private, so that any member of this package
- * can acquire the access token, and give it away to trusted friends.
- */
- static final Access TOKEN = new Access();
-
- /**
- * @return Access.TOKEN, if the caller is a friend of this package
- */
- public static Access getToken() {
- Class> callc = Reflection.getCallerClass(2);
- if (isFriend(callc))
- return TOKEN;
- else
- throw new IllegalAccessError("bad caller: " + callc);
- }
-
- /** Is the given name the name of a class which could be our friend? */
- public static boolean isFriendName(String name) {
- for (String friend : FRIENDS) {
- if (name.startsWith(friend))
- return true;
- }
- return false;
- }
-
- /** Is the given class a friend? True if {@link #isFriendName},
- * and the given class also shares a class loader with us.
- */
- public static boolean isFriend(Class> c) {
- return isFriendName(c.getName()) && c.getClassLoader() == CLASS_LOADER;
- }
-
- private static final ClassLoader CLASS_LOADER = Access.class.getClassLoader();
-
- /**
- * Throw an IllegalAccessError if the caller does not possess
- * the Access.TOKEN.
- * @param must be Access.TOKEN
- */
- public static void check(Access token) {
- if (token == null)
- fail();
- // else it must be the unique Access.TOKEN
- assert(token == Access.TOKEN);
- }
- private static void fail() {
- final int CALLER_DEPTH = 3;
- // 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller
- Class> callc = Reflection.getCallerClass(CALLER_DEPTH);
- throw new IllegalAccessError("bad caller: " + callc);
- }
-
- static {
- //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
- }
-}
diff --git a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java
deleted file mode 100644
index 703788ff484..00000000000
--- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, 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 sun.dyn;
-
-import java.dyn.*;
-import static sun.dyn.MemberName.uncaughtException;
-
-/**
- * Parts of CallSite known to the JVM.
- * @author jrose
- */
-public class CallSiteImpl {
- // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
- static CallSite makeSite(MethodHandle bootstrapMethod,
- // Callee information:
- String name, MethodType type,
- // Extra arguments for BSM, if any:
- Object info,
- // Caller information:
- MemberName callerMethod, int callerBCI) {
- Class> callerClass = callerMethod.getDeclaringClass();
- Object caller;
- if (bootstrapMethod.type().parameterType(0) == Class.class && TRANSITIONAL_BEFORE_PFD)
- caller = callerClass; // remove for PFD
- else
- caller = MethodHandleImpl.IMPL_LOOKUP.in(callerClass);
- if (bootstrapMethod == null && TRANSITIONAL_BEFORE_PFD) {
- // If there is no bootstrap method, throw IncompatibleClassChangeError.
- // This is a valid generic error type for resolution (JLS 12.3.3).
- throw new IncompatibleClassChangeError
- ("Class "+callerClass.getName()+" has not declared a bootstrap method for invokedynamic");
- }
- CallSite site;
- try {
- Object binding;
- info = maybeReBox(info);
- if (info == null) {
- binding = bootstrapMethod.invokeGeneric(caller, name, type);
- } else if (!info.getClass().isArray()) {
- binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
- } else {
- Object[] argv = (Object[]) info;
- if (3 + argv.length > 255)
- new InvokeDynamicBootstrapError("too many bootstrap method arguments");
- MethodType bsmType = bootstrapMethod.type();
- if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
- binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
- else
- binding = MethodHandles.spreadInvoker(bsmType, 3)
- .invokeGeneric(bootstrapMethod, caller, name, type, argv);
- }
- //System.out.println("BSM for "+name+type+" => "+binding);
- if (binding instanceof CallSite) {
- site = (CallSite) binding;
- } else if (binding instanceof MethodHandle && TRANSITIONAL_BEFORE_PFD) {
- // Transitional!
- MethodHandle target = (MethodHandle) binding;
- site = new ConstantCallSite(target);
- } else {
- throw new ClassCastException("bootstrap method failed to produce a CallSite");
- }
- if (TRANSITIONAL_BEFORE_PFD)
- PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type,
- callerMethod, callerBCI);
- assert(site.getTarget() != null);
- assert(site.getTarget().type().equals(type));
- } catch (Throwable ex) {
- InvokeDynamicBootstrapError bex;
- if (ex instanceof InvokeDynamicBootstrapError)
- bex = (InvokeDynamicBootstrapError) ex;
- else
- bex = new InvokeDynamicBootstrapError("call site initialization exception", ex);
- throw bex;
- }
- return site;
- }
-
- private static boolean TRANSITIONAL_BEFORE_PFD = true; // FIXME: remove for PFD
-
- private static Object maybeReBox(Object x) {
- if (x instanceof Integer) {
- int xi = (int) x;
- if (xi == (byte) xi)
- x = xi; // must rebox; see JLS 5.1.7
- return x;
- } else if (x instanceof Object[]) {
- Object[] xa = (Object[]) x;
- for (int i = 0; i < xa.length; i++) {
- if (xa[i] instanceof Integer)
- xa[i] = maybeReBox(xa[i]);
- }
- return xa;
- } else {
- return x;
- }
- }
-
- // This method is private in CallSite because it touches private fields in CallSite.
- // These private fields (vmmethod, vmindex) are specific to the JVM.
- private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
- static {
- try {
- PRIVATE_INITIALIZE_CALL_SITE =
- !TRANSITIONAL_BEFORE_PFD ? null :
- MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
- MethodType.methodType(void.class,
- String.class, MethodType.class,
- MemberName.class, int.class));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
-
- public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) {
- Access.check(token);
- MethodHandleNatives.setCallSiteTarget(site, target);
- }
-}
diff --git a/jdk/src/share/classes/sun/font/FileFont.java b/jdk/src/share/classes/sun/font/FileFont.java
index 22096dda2eb..1c63e9f1159 100644
--- a/jdk/src/share/classes/sun/font/FileFont.java
+++ b/jdk/src/share/classes/sun/font/FileFont.java
@@ -32,22 +32,13 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
import sun.java2d.Disposer;
import sun.java2d.DisposerRecord;
-import java.lang.ref.WeakReference;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteOrder;
-import java.nio.MappedByteBuffer;
-import java.nio.BufferUnderflowException;
-import java.nio.channels.ClosedChannelException;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.awt.Font;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
public abstract class FileFont extends PhysicalFont {
@@ -286,4 +277,49 @@ public abstract class FileFont extends PhysicalFont {
});
}
}
+
+ protected String getPublicFileName() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return platName;
+ }
+ boolean canReadProperty = true;
+
+ try {
+ sm.checkPropertyAccess("java.io.tmpdir");
+ } catch (SecurityException e) {
+ canReadProperty = false;
+ }
+
+ if (canReadProperty) {
+ return platName;
+ }
+
+ final File f = new File(platName);
+
+ Boolean isTmpFile = Boolean.FALSE;
+ try {
+ isTmpFile = AccessController.doPrivileged(
+ new PrivilegedExceptionAction() {
+ public Boolean run() {
+ File tmp = new File(System.getProperty("java.io.tmpdir"));
+ try {
+ String tpath = tmp.getCanonicalPath();
+ String fpath = f.getCanonicalPath();
+
+ return (fpath == null) || fpath.startsWith(tpath);
+ } catch (IOException e) {
+ return Boolean.TRUE;
+ }
+ }
+ }
+ );
+ } catch (PrivilegedActionException e) {
+ // unable to verify whether value of java.io.tempdir will be
+ // exposed, so return only a name of the font file.
+ isTmpFile = Boolean.TRUE;
+ }
+
+ return isTmpFile ? "temp file" : platName;
+ }
}
diff --git a/jdk/src/share/classes/sun/font/TrueTypeFont.java b/jdk/src/share/classes/sun/font/TrueTypeFont.java
index e448338a3f3..84cbd2c9a34 100644
--- a/jdk/src/share/classes/sun/font/TrueTypeFont.java
+++ b/jdk/src/share/classes/sun/font/TrueTypeFont.java
@@ -519,7 +519,8 @@ public class TrueTypeFont extends FileFont {
break;
default:
- throw new FontFormatException("Unsupported sfnt " + platName);
+ throw new FontFormatException("Unsupported sfnt " +
+ getPublicFileName());
}
/* Now have the offset of this TT font (possibly within a TTC)
@@ -1680,7 +1681,6 @@ public class TrueTypeFont extends FileFont {
@Override
public String toString() {
return "** TrueType Font: Family="+familyName+ " Name="+fullName+
- " style="+style+" fileName="+platName;
+ " style="+style+" fileName="+getPublicFileName();
}
-
}
diff --git a/jdk/src/share/classes/sun/font/Type1Font.java b/jdk/src/share/classes/sun/font/Type1Font.java
index 48821dd94e5..5fa49bd132d 100644
--- a/jdk/src/share/classes/sun/font/Type1Font.java
+++ b/jdk/src/share/classes/sun/font/Type1Font.java
@@ -677,6 +677,6 @@ public class Type1Font extends FileFont {
public String toString() {
return "** Type1 Font: Family="+familyName+ " Name="+fullName+
- " style="+style+" fileName="+platName;
+ " style="+style+" fileName="+getPublicFileName();
}
}
diff --git a/jdk/src/share/classes/sun/dyn/WrapperInstance.java b/jdk/src/share/classes/sun/invoke/WrapperInstance.java
similarity index 90%
rename from jdk/src/share/classes/sun/dyn/WrapperInstance.java
rename to jdk/src/share/classes/sun/invoke/WrapperInstance.java
index d6e91fd0d03..ba918b4d9d2 100644
--- a/jdk/src/share/classes/sun/dyn/WrapperInstance.java
+++ b/jdk/src/share/classes/sun/invoke/WrapperInstance.java
@@ -23,14 +23,14 @@
* questions.
*/
-package sun.dyn;
+package sun.invoke;
-import java.dyn.MethodHandle;
+import java.lang.invoke.MethodHandle;
/**
- * Private API used inside of java.dyn.MethodHandles.
+ * Private API used inside of java.lang.invoke.MethodHandles.
* Interface implemented by every object which is produced by
- * {@link java.dyn.MethodHandles#asInstance MethodHandles.asInstance}.
+ * {@link java.lang.invoke.MethodHandles#asInstance MethodHandles.asInstance}.
* The methods of this interface allow a caller to recover the parameters
* to {@code asInstance}.
* This allows applications to repeatedly convert between method handles
diff --git a/jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java
rename to jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java
index bd7c5cb59dd..3005a452f71 100644
--- a/jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java
+++ b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.anon;
+package sun.invoke.anon;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
diff --git a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java
rename to jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java
index b68b3f650c9..441ba957336 100644
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,14 +23,14 @@
* questions.
*/
-package sun.dyn.anon;
+package sun.invoke.anon;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
-import static sun.dyn.anon.ConstantPoolVisitor.*;
+import static sun.invoke.anon.ConstantPoolVisitor.*;
/** A constant pool parser.
*/
diff --git a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java
rename to jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java
index 87dc97f6025..259d4b2336e 100644
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.anon;
+package sun.invoke.anon;
import java.io.IOException;
import java.io.OutputStream;
@@ -32,7 +32,7 @@ import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
-import static sun.dyn.anon.ConstantPoolVisitor.*;
+import static sun.invoke.anon.ConstantPoolVisitor.*;
/** A class and its patched constant pool.
*
diff --git a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java
similarity index 98%
rename from jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java
rename to jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java
index e882b7d6724..dfec8b41151 100644
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.anon;
+package sun.invoke.anon;
/**
* A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
diff --git a/jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java b/jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java
similarity index 94%
rename from jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java
rename to jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java
index 555bb428f3f..d420d34b0d6 100644
--- a/jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java
+++ b/jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.anon;
+package sun.invoke.anon;
/** Exception used when there is an error in the constant pool
* format.
diff --git a/jdk/src/share/classes/sun/dyn/empty/Empty.java b/jdk/src/share/classes/sun/invoke/empty/Empty.java
similarity index 90%
rename from jdk/src/share/classes/sun/dyn/empty/Empty.java
rename to jdk/src/share/classes/sun/invoke/empty/Empty.java
index 416a6f128e8..f75d2b3d016 100644
--- a/jdk/src/share/classes/sun/dyn/empty/Empty.java
+++ b/jdk/src/share/classes/sun/invoke/empty/Empty.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, 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
@@ -23,14 +23,14 @@
* questions.
*/
-package sun.dyn.empty;
+package sun.invoke.empty;
/**
* An empty class in an empty package.
* Used as a proxy for unprivileged code, since making access checks
* against it will only succeed against public methods in public types.
*
- * This class also stands (internally to sun.dyn) for the type of a
+ * This class also stands (internally to sun.invoke) for the type of a
* value that cannot be produced, because the expression of this type
* always returns abnormally. (Cf. Nothing in the closures proposal.)
* @author jrose
diff --git a/jdk/src/share/classes/sun/dyn/package-info.java b/jdk/src/share/classes/sun/invoke/package-info.java
similarity index 93%
rename from jdk/src/share/classes/sun/dyn/package-info.java
rename to jdk/src/share/classes/sun/invoke/package-info.java
index d129b0f5a27..74999fe6c7e 100644
--- a/jdk/src/share/classes/sun/dyn/package-info.java
+++ b/jdk/src/share/classes/sun/invoke/package-info.java
@@ -24,8 +24,8 @@
*/
/**
- * Implementation details for JSR 292 RI, package java.dyn.
+ * Implementation details for JSR 292 RI, package java.lang.invoke.
* @author jrose
*/
-package sun.dyn;
+package sun.invoke;
diff --git a/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java b/jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java
similarity index 97%
rename from jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java
rename to jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java
index 2c59b918338..ccc313cd41b 100644
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,9 +23,9 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
-import java.dyn.MethodType;
+import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.List;
diff --git a/jdk/src/share/classes/sun/dyn/util/BytecodeName.java b/jdk/src/share/classes/sun/invoke/util/BytecodeName.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/util/BytecodeName.java
rename to jdk/src/share/classes/sun/invoke/util/BytecodeName.java
index 73be3fb1361..9b8fa35cb70 100644
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeName.java
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeName.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
/**
* Utility routines for dealing with bytecode-level names.
diff --git a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java
similarity index 94%
rename from jdk/src/share/classes/sun/dyn/util/ValueConversions.java
rename to jdk/src/share/classes/sun/invoke/util/ValueConversions.java
index 374bd245058..c6a56abf665 100644
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java
+++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,22 +23,19 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
-import sun.dyn.Access;
-import sun.dyn.AdapterMethodHandle;
-import sun.dyn.MethodHandleImpl;
-import static sun.dyn.MemberName.uncaughtException;
public class ValueConversions {
- private static final Access IMPL_TOKEN = Access.getToken();
- private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN);
+ private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
private static EnumMap[] newWrapperCaches(int n) {
@SuppressWarnings("unchecked")
@@ -157,7 +154,7 @@ public class ValueConversions {
mh = null;
}
} else {
- mh = retype(type, unbox(wrap, !exact, raw));
+ mh = unbox(wrap, !exact, raw).asType(type);
}
if (mh != null) {
cache.put(wrap, mh);
@@ -293,7 +290,7 @@ public class ValueConversions {
mh = null;
}
} else {
- mh = retype(type.erase(), box(wrap, !exact, raw));
+ mh = box(wrap, !exact, raw).asType(type.erase());
}
if (mh != null) {
cache.put(wrap, mh);
@@ -412,7 +409,7 @@ public class ValueConversions {
mh = null;
}
} else {
- mh = retype(IDENTITY.type(), rebox(wrap, !exact));
+ mh = rebox(wrap, !exact).asType(IDENTITY.type());
}
if (mh != null) {
cache.put(wrap, mh);
@@ -504,8 +501,8 @@ public class ValueConversions {
// use the raw method
Wrapper rawWrap = wrap.rawPrimitive();
- if (rawWrap != wrap) {
- mh = retype(type, zeroConstantFunction(rawWrap));
+ if (mh == null && rawWrap != wrap) {
+ mh = MethodHandles.explicitCastArguments(zeroConstantFunction(rawWrap), type);
}
if (mh != null) {
cache.put(wrap, mh);
@@ -552,6 +549,22 @@ public class ValueConversions {
return x;
}
+ static byte identity(byte x) {
+ return x;
+ }
+
+ static short identity(short x) {
+ return x;
+ }
+
+ static boolean identity(boolean x) {
+ return x;
+ }
+
+ static char identity(char x) {
+ return x;
+ }
+
/**
* Identity function on longs.
* @param x an arbitrary long value
@@ -561,6 +574,14 @@ public class ValueConversions {
return x;
}
+ static float identity(float x) {
+ return x;
+ }
+
+ static double identity(double x) {
+ return x;
+ }
+
/**
* Identity function, with reference cast.
* @param t an arbitrary reference type
@@ -590,7 +611,9 @@ public class ValueConversions {
IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
} catch (Exception ex) {
- throw uncaughtException(ex);
+ Error err = new InternalError("uncaught exception");
+ err.initCause(ex);
+ throw err;
}
}
@@ -622,7 +645,8 @@ public class ValueConversions {
mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
if (exact) {
MethodType xmt = MethodType.methodType(type, Object.class);
- mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
+ mh = MethodHandles.explicitCastArguments(mh, xmt);
+ //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
}
if (cache != null)
cache.put(wrap, mh);
@@ -634,15 +658,11 @@ public class ValueConversions {
}
public static MethodHandle identity(Class> type) {
- if (type == Object.class)
- return IDENTITY;
- else if (!type.isPrimitive())
- return retype(MethodType.methodType(type, type), IDENTITY);
- else
- return identity(Wrapper.forPrimitiveType(type));
+ // This stuff has been moved into MethodHandles:
+ return MethodHandles.identity(type);
}
- static MethodHandle identity(Wrapper wrap) {
+ public static MethodHandle identity(Wrapper wrap) {
EnumMap cache = CONSTANT_FUNCTIONS[1];
MethodHandle mh = cache.get(wrap);
if (mh != null) {
@@ -665,12 +685,6 @@ public class ValueConversions {
return mh;
}
- // use a raw conversion
- if (wrap.isSingleWord() && wrap != Wrapper.INT) {
- mh = retype(type, identity(Wrapper.INT));
- } else if (wrap.isDoubleWord() && wrap != Wrapper.LONG) {
- mh = retype(type, identity(Wrapper.LONG));
- }
if (mh != null) {
cache.put(wrap, mh);
return mh;
@@ -678,10 +692,6 @@ public class ValueConversions {
throw new IllegalArgumentException("cannot find identity for " + wrap);
}
- private static MethodHandle retype(MethodType type, MethodHandle mh) {
- return AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, type, mh);
- }
-
private static final Object[] NO_ARGS_ARRAY = {};
private static Object[] makeArray(Object... args) { return args; }
private static Object[] array() { return NO_ARGS_ARRAY; }
diff --git a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
similarity index 98%
rename from jdk/src/share/classes/sun/dyn/util/VerifyAccess.java
rename to jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
index 1114bad2695..657aeec23d8 100644
--- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,12 +23,9 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
import java.lang.reflect.Modifier;
-import sun.dyn.MemberName;
-import sun.dyn.MethodHandleImpl;
-import sun.dyn.empty.Empty;
import static java.lang.reflect.Modifier.*;
/**
diff --git a/jdk/src/share/classes/sun/dyn/util/VerifyType.java b/jdk/src/share/classes/sun/invoke/util/VerifyType.java
similarity index 98%
rename from jdk/src/share/classes/sun/dyn/util/VerifyType.java
rename to jdk/src/share/classes/sun/invoke/util/VerifyType.java
index b6277e4a8a9..39286d09ca4 100644
--- a/jdk/src/share/classes/sun/dyn/util/VerifyType.java
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,10 +23,10 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
-import java.dyn.MethodType;
-import sun.dyn.empty.Empty;
+import java.lang.invoke.MethodType;
+import sun.invoke.empty.Empty;
/**
* This class centralizes information about the JVM verifier
diff --git a/jdk/src/share/classes/sun/dyn/util/Wrapper.java b/jdk/src/share/classes/sun/invoke/util/Wrapper.java
similarity index 99%
rename from jdk/src/share/classes/sun/dyn/util/Wrapper.java
rename to jdk/src/share/classes/sun/invoke/util/Wrapper.java
index 91b599e8c64..8e2ce578386 100644
--- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java
+++ b/jdk/src/share/classes/sun/invoke/util/Wrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -23,7 +23,7 @@
* questions.
*/
-package sun.dyn.util;
+package sun.invoke.util;
public enum Wrapper {
BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
@@ -267,7 +267,7 @@ public enum Wrapper {
FROM_WRAP[wi] = w;
FROM_CHAR[ci] = w;
}
- //assert(jdk.sun.dyn.util.WrapperTest.test(false));
+ //assert(jdk.sun.invoke.util.WrapperTest.test(false));
}
/** What is the primitive type wrapped by this wrapper? */
diff --git a/jdk/src/share/classes/sun/dyn/util/package-info.java b/jdk/src/share/classes/sun/invoke/util/package-info.java
similarity index 88%
rename from jdk/src/share/classes/sun/dyn/util/package-info.java
rename to jdk/src/share/classes/sun/invoke/util/package-info.java
index 0977b22ef94..785ca804302 100644
--- a/jdk/src/share/classes/sun/dyn/util/package-info.java
+++ b/jdk/src/share/classes/sun/invoke/util/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, 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
@@ -24,8 +24,8 @@
*/
/**
- * Extra support for using JSR 292 RI, package java.dyn.
+ * Extra support for using JSR 292 RI, package java.lang.invoke.
* @author jrose
*/
-package sun.dyn.util;
+package sun.invoke.util;
diff --git a/jdk/src/share/classes/sun/java2d/pisces/Helpers.java b/jdk/src/share/classes/sun/java2d/pisces/Helpers.java
index b91bc6a400a..42c7f2654d3 100644
--- a/jdk/src/share/classes/sun/java2d/pisces/Helpers.java
+++ b/jdk/src/share/classes/sun/java2d/pisces/Helpers.java
@@ -154,9 +154,6 @@ final class Helpers {
// These use a hardcoded factor of 2 for increasing sizes. Perhaps this
// should be provided as an argument.
static float[] widenArray(float[] in, final int cursize, final int numToAdd) {
- if (in == null) {
- return new float[5 * numToAdd];
- }
if (in.length >= cursize + numToAdd) {
return in;
}
diff --git a/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java b/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java
index ba91edb9819..3d6046bed69 100644
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java
@@ -191,8 +191,7 @@ final class PiscesTileGenerator implements AATileGenerator {
System.out.println("len = "+runLen);
System.out.print(cache.toString());
e0.printStackTrace();
- System.exit(1);
- return;
+ throw e0;
}
int rx0 = cx;
@@ -215,8 +214,7 @@ final class PiscesTileGenerator implements AATileGenerator {
System.out.println("len = "+runLen);
System.out.print(cache.toString());
e.printStackTrace();
- System.exit(1);
- return;
+ throw e;
}
}
pos += 2;
@@ -250,4 +248,5 @@ final class PiscesTileGenerator implements AATileGenerator {
* No further calls will be made on this instance.
*/
public void dispose() {}
-}
\ No newline at end of file
+}
+
diff --git a/jdk/src/share/classes/sun/java2d/pisces/Renderer.java b/jdk/src/share/classes/sun/java2d/pisces/Renderer.java
index cbfa2897d94..6d07b532e08 100644
--- a/jdk/src/share/classes/sun/java2d/pisces/Renderer.java
+++ b/jdk/src/share/classes/sun/java2d/pisces/Renderer.java
@@ -47,16 +47,16 @@ final class Renderer implements PathConsumer2D {
private static final int INIT_CROSSINGS_SIZE = 10;
- private ScanlineIterator() {
+ // Preconditions: Only subpixel scanlines in the range
+ // (start <= subpixel_y <= end) will be evaluated. No
+ // edge may have a valid (i.e. inside the supplied clip)
+ // crossing that would be generated outside that range.
+ private ScanlineIterator(int start, int end) {
crossings = new int[INIT_CROSSINGS_SIZE];
edgePtrs = new int[INIT_CROSSINGS_SIZE];
- // We don't care if we clip some of the line off with ceil, since
- // no scan line crossings will be eliminated (in fact, the ceil is
- // the y of the first scan line crossing).
- final int minY = getFirstScanLineCrossing();
- nextY = minY;
- maxY = getScanLineCrossingEnd()-1;
+ nextY = start;
+ maxY = end;
edgeCount = 0;
}
@@ -148,6 +148,7 @@ final class Renderer implements PathConsumer2D {
// don't just set NULL to -1, because we want NULL+NEXT to be negative.
private static final int NULL = -SIZEOF_EDGE;
private float[] edges = null;
+ private static final int INIT_NUM_EDGES = 8;
private int[] edgeBuckets = null;
private int[] edgeBucketCounts = null; // 2*newedges + (1 if pruning needed)
private int numEdges;
@@ -156,7 +157,7 @@ final class Renderer implements PathConsumer2D {
private static final float INC_BND = 8f;
// each bucket is a linked list. this method adds eptr to the
- // start "bucket"th linked list.
+ // start of the "bucket"th linked list.
private void addEdgeToBucket(final int eptr, final int bucket) {
edges[eptr+NEXT] = edgeBuckets[bucket];
edgeBuckets[bucket] = eptr;
@@ -168,7 +169,8 @@ final class Renderer implements PathConsumer2D {
// X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
private void quadBreakIntoLinesAndAdd(float x0, float y0,
final Curve c,
- final float x2, final float y2) {
+ final float x2, final float y2)
+ {
final float QUAD_DEC_BND = 32;
final int countlg = 4;
int count = 1 << countlg;
@@ -204,7 +206,8 @@ final class Renderer implements PathConsumer2D {
// here, but then too many numbers are passed around.
private void curveBreakIntoLinesAndAdd(float x0, float y0,
final Curve c,
- final float x3, final float y3) {
+ final float x3, final float y3)
+ {
final int countlg = 3;
int count = 1 << countlg;
@@ -259,8 +262,6 @@ final class Renderer implements PathConsumer2D {
}
}
- // Preconditions: y2 > y1 and the curve must cross some scanline
- // i.e.: y1 <= y < y2 for some y such that boundsMinY <= y < boundsMaxY
private void addLine(float x1, float y1, float x2, float y2) {
float or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
if (y2 < y1) {
@@ -272,12 +273,11 @@ final class Renderer implements PathConsumer2D {
x1 = or;
or = 0;
}
- final int firstCrossing = Math.max((int) Math.ceil(y1), boundsMinY);
+ final int firstCrossing = Math.max((int)Math.ceil(y1), boundsMinY);
final int lastCrossing = Math.min((int)Math.ceil(y2), boundsMaxY);
if (firstCrossing >= lastCrossing) {
return;
}
-
if (y1 < edgeMinY) { edgeMinY = y1; }
if (y2 > edgeMaxY) { edgeMaxY = y2; }
@@ -297,22 +297,10 @@ final class Renderer implements PathConsumer2D {
edges[ptr+OR] = or;
edges[ptr+CURX] = x1 + (firstCrossing - y1) * slope;
edges[ptr+SLOPE] = slope;
- edges[ptr+YMAX] = y2;
+ edges[ptr+YMAX] = lastCrossing;
final int bucketIdx = firstCrossing - boundsMinY;
addEdgeToBucket(ptr, bucketIdx);
- if (lastCrossing < boundsMaxY) {
- edgeBucketCounts[lastCrossing - boundsMinY] |= 1;
- }
- }
-
- // preconditions: should not be called before the last line has been added
- // to the edge list (even though it will return a correct answer at that
- // point in time, it's not meant to be used that way).
- private int getFirstScanLineCrossing() {
- return Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
- }
- private int getScanLineCrossingEnd() {
- return Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
+ edgeBucketCounts[lastCrossing - boundsMinY] |= 1;
}
// END EDGE LIST
@@ -366,9 +354,11 @@ final class Renderer implements PathConsumer2D {
this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X;
this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y;
+ edges = new float[INIT_NUM_EDGES * SIZEOF_EDGE];
+ numEdges = 0;
edgeBuckets = new int[boundsMaxY - boundsMinY];
java.util.Arrays.fill(edgeBuckets, NULL);
- edgeBucketCounts = new int[edgeBuckets.length];
+ edgeBucketCounts = new int[edgeBuckets.length + 1];
}
private float tosubpixx(float pix_x) {
@@ -394,7 +384,7 @@ final class Renderer implements PathConsumer2D {
y0 = y1;
}
- Curve c = new Curve();
+ private Curve c = new Curve();
@Override public void curveTo(float x1, float y1,
float x2, float y2,
float x3, float y3)
@@ -431,8 +421,8 @@ final class Renderer implements PathConsumer2D {
throw new InternalError("Renderer does not use a native consumer.");
}
- private void _endRendering(final int pix_bboxx0, final int pix_bboxy0,
- final int pix_bboxx1, final int pix_bboxy1)
+ private void _endRendering(final int pix_bboxx0, final int pix_bboxx1,
+ int ymin, int ymax)
{
// Mask to determine the relevant bit of the crossing sum
// 0x1 if EVEN_ODD, all bits if NON_ZERO
@@ -455,7 +445,7 @@ final class Renderer implements PathConsumer2D {
int pix_minX = Integer.MAX_VALUE;
int y = boundsMinY; // needs to be declared here so we emit the last row properly.
- ScanlineIterator it = this.new ScanlineIterator();
+ ScanlineIterator it = this.new ScanlineIterator(ymin, ymax);
for ( ; it.hasNext(); ) {
int numCrossings = it.next();
int[] crossings = it.crossings;
@@ -477,7 +467,7 @@ final class Renderer implements PathConsumer2D {
int curxo = crossings[i];
int curx = curxo >> 1;
// to turn {0, 1} into {-1, 1}, multiply by 2 and subtract 1.
- int crorientation = ((curxo & 0x1) << 1) -1;
+ int crorientation = ((curxo & 0x1) << 1) - 1;
if ((sum & mask) != 0) {
int x0 = Math.max(prev, bboxx0);
int x1 = Math.min(curx, bboxx1);
@@ -541,7 +531,7 @@ final class Renderer implements PathConsumer2D {
}
this.cache = new PiscesCache(pminX, pminY, pmaxX, pmaxY);
- _endRendering(pminX, pminY, pmaxX, pmaxY);
+ _endRendering(pminX, pmaxX, spminY, spmaxY);
}
public PiscesCache getCache() {
diff --git a/jdk/src/share/classes/sun/java2d/pisces/Stroker.java b/jdk/src/share/classes/sun/java2d/pisces/Stroker.java
index b898febc4c2..f7323f95adb 100644
--- a/jdk/src/share/classes/sun/java2d/pisces/Stroker.java
+++ b/jdk/src/share/classes/sun/java2d/pisces/Stroker.java
@@ -764,6 +764,11 @@ final class Stroker implements PathConsumer2D {
private static final int MAX_N_CURVES = 11;
private float[] subdivTs = new float[MAX_N_CURVES - 1];
+ // If this class is compiled with ecj, then Hotspot crashes when OSR
+ // compiling this function. See bugs 7004570 and 6675699
+ // TODO: until those are fixed, we should work around that by
+ // manually inlining this into curveTo and quadTo.
+/******************************* WORKAROUND **********************************
private void somethingTo(final int type) {
// need these so we can update the state at the end of this method
final float xf = middle[type-2], yf = middle[type-1];
@@ -866,6 +871,7 @@ final class Stroker implements PathConsumer2D {
this.cy0 = yf;
this.prev = DRAWING_OP_TO;
}
+****************************** END WORKAROUND *******************************/
// finds values of t where the curve in pts should be subdivided in order
// to get good offset curves a distance of w away from the middle curve.
@@ -932,18 +938,168 @@ final class Stroker implements PathConsumer2D {
middle[2] = x1; middle[3] = y1;
middle[4] = x2; middle[5] = y2;
middle[6] = x3; middle[7] = y3;
- somethingTo(8);
- }
- @Override public long getNativeConsumer() {
- throw new InternalError("Stroker doesn't use a native consumer");
+ // inlined version of somethingTo(8);
+ // See the TODO on somethingTo
+
+ // need these so we can update the state at the end of this method
+ final float xf = middle[6], yf = middle[7];
+ float dxs = middle[2] - middle[0];
+ float dys = middle[3] - middle[1];
+ float dxf = middle[6] - middle[4];
+ float dyf = middle[7] - middle[5];
+
+ boolean p1eqp2 = (dxs == 0f && dys == 0f);
+ boolean p3eqp4 = (dxf == 0f && dyf == 0f);
+ if (p1eqp2) {
+ dxs = middle[4] - middle[0];
+ dys = middle[5] - middle[1];
+ if (dxs == 0f && dys == 0f) {
+ dxs = middle[6] - middle[0];
+ dys = middle[7] - middle[1];
+ }
+ }
+ if (p3eqp4) {
+ dxf = middle[6] - middle[2];
+ dyf = middle[7] - middle[3];
+ if (dxf == 0f && dyf == 0f) {
+ dxf = middle[6] - middle[0];
+ dyf = middle[7] - middle[1];
+ }
+ }
+ if (dxs == 0f && dys == 0f) {
+ // this happens iff the "curve" is just a point
+ lineTo(middle[0], middle[1]);
+ return;
+ }
+
+ // if these vectors are too small, normalize them, to avoid future
+ // precision problems.
+ if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
+ float len = (float)Math.sqrt(dxs*dxs + dys*dys);
+ dxs /= len;
+ dys /= len;
+ }
+ if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
+ float len = (float)Math.sqrt(dxf*dxf + dyf*dyf);
+ dxf /= len;
+ dyf /= len;
+ }
+
+ computeOffset(dxs, dys, lineWidth2, offset[0]);
+ final float mx = offset[0][0];
+ final float my = offset[0][1];
+ drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
+
+ int nSplits = findSubdivPoints(middle, subdivTs, 8, lineWidth2);
+
+ int kind = 0;
+ Iterator it = Curve.breakPtsAtTs(middle, 8, subdivTs, nSplits);
+ while(it.hasNext()) {
+ int curCurveOff = it.next();
+
+ kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
+ if (kind != 0) {
+ emitLineTo(lp[0], lp[1]);
+ switch(kind) {
+ case 8:
+ emitCurveTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], lp[6], lp[7], false);
+ emitCurveTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7], true);
+ break;
+ case 4:
+ emitLineTo(lp[2], lp[3]);
+ emitLineTo(rp[0], rp[1], true);
+ break;
+ }
+ emitLineTo(rp[kind - 2], rp[kind - 1], true);
+ }
+ }
+
+ this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
+ this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
+ this.cdx = dxf;
+ this.cdy = dyf;
+ this.cx0 = xf;
+ this.cy0 = yf;
+ this.prev = DRAWING_OP_TO;
}
@Override public void quadTo(float x1, float y1, float x2, float y2) {
middle[0] = cx0; middle[1] = cy0;
middle[2] = x1; middle[3] = y1;
middle[4] = x2; middle[5] = y2;
- somethingTo(6);
+
+ // inlined version of somethingTo(8);
+ // See the TODO on somethingTo
+
+ // need these so we can update the state at the end of this method
+ final float xf = middle[4], yf = middle[5];
+ float dxs = middle[2] - middle[0];
+ float dys = middle[3] - middle[1];
+ float dxf = middle[4] - middle[2];
+ float dyf = middle[5] - middle[3];
+ if ((dxs == 0f && dys == 0f) || (dxf == 0f && dyf == 0f)) {
+ dxs = dxf = middle[4] - middle[0];
+ dys = dyf = middle[5] - middle[1];
+ }
+ if (dxs == 0f && dys == 0f) {
+ // this happens iff the "curve" is just a point
+ lineTo(middle[0], middle[1]);
+ return;
+ }
+ // if these vectors are too small, normalize them, to avoid future
+ // precision problems.
+ if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
+ float len = (float)Math.sqrt(dxs*dxs + dys*dys);
+ dxs /= len;
+ dys /= len;
+ }
+ if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
+ float len = (float)Math.sqrt(dxf*dxf + dyf*dyf);
+ dxf /= len;
+ dyf /= len;
+ }
+
+ computeOffset(dxs, dys, lineWidth2, offset[0]);
+ final float mx = offset[0][0];
+ final float my = offset[0][1];
+ drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
+
+ int nSplits = findSubdivPoints(middle, subdivTs, 6, lineWidth2);
+
+ int kind = 0;
+ Iterator it = Curve.breakPtsAtTs(middle, 6, subdivTs, nSplits);
+ while(it.hasNext()) {
+ int curCurveOff = it.next();
+
+ kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
+ if (kind != 0) {
+ emitLineTo(lp[0], lp[1]);
+ switch(kind) {
+ case 6:
+ emitQuadTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], false);
+ emitQuadTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], true);
+ break;
+ case 4:
+ emitLineTo(lp[2], lp[3]);
+ emitLineTo(rp[0], rp[1], true);
+ break;
+ }
+ emitLineTo(rp[kind - 2], rp[kind - 1], true);
+ }
+ }
+
+ this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
+ this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
+ this.cdx = dxf;
+ this.cdy = dyf;
+ this.cx0 = xf;
+ this.cy0 = yf;
+ this.prev = DRAWING_OP_TO;
+ }
+
+ @Override public long getNativeConsumer() {
+ throw new InternalError("Stroker doesn't use a native consumer");
}
// a stack of polynomial curves where each curve shares endpoints with
diff --git a/jdk/src/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/share/classes/sun/launcher/LauncherHelper.java
index ff71e8908b1..bd0b72e47ab 100644
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java
@@ -42,10 +42,12 @@ package sun.launcher;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.nio.charset.Charset;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -471,11 +473,11 @@ public enum LauncherHelper {
} catch (ClassNotFoundException cnfe) {
abort(ostream, cnfe, "java.launcher.cls.error1", cn);
}
- signatureDiagnostic(ostream, c);
+ getMainMethod(ostream, c);
return c;
}
- static void signatureDiagnostic(PrintStream ostream, Class> clazz) {
+ static Method getMainMethod(PrintStream ostream, Class> clazz) {
String classname = clazz.getName();
Method method = null;
try {
@@ -495,6 +497,31 @@ public enum LauncherHelper {
if (method.getReturnType() != java.lang.Void.TYPE) {
abort(ostream, null, "java.launcher.cls.error3", classname);
}
- return;
+ return method;
+ }
+
+ private static final String encprop = "sun.jnu.encoding";
+ private static String encoding = null;
+ private static boolean isCharsetSupported = false;
+
+ /*
+ * converts a c or a byte array to a platform specific string,
+ * previously implemented as a native method in the launcher.
+ */
+ static String makePlatformString(boolean printToStderr, byte[] inArray) {
+ final PrintStream ostream = (printToStderr) ? System.err : System.out;
+ if (encoding == null) {
+ encoding = System.getProperty(encprop);
+ isCharsetSupported = Charset.isSupported(encoding);
+ }
+ try {
+ String out = isCharsetSupported
+ ? new String(inArray, encoding)
+ : new String(inArray);
+ return out;
+ } catch (UnsupportedEncodingException uee) {
+ abort(ostream, uee, null);
+ }
+ return null; // keep the compiler happy
}
}
diff --git a/jdk/src/share/classes/java/dyn/MethodTypeForm.java b/jdk/src/share/classes/sun/misc/JavaSecurityAccess.java
similarity index 68%
rename from jdk/src/share/classes/java/dyn/MethodTypeForm.java
rename to jdk/src/share/classes/sun/misc/JavaSecurityAccess.java
index 35c59a45c0c..5a3aa513fb8 100644
--- a/jdk/src/share/classes/java/dyn/MethodTypeForm.java
+++ b/jdk/src/share/classes/sun/misc/JavaSecurityAccess.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,17 +23,18 @@
* questions.
*/
-package java.dyn;
+package sun.misc;
-/**
- * TO DO: Temporary shim; remove after refactoring effects are complete in JVM.
- * @author John Rose
- */
-import sun.dyn.MethodTypeImpl;
+import java.security.AccessControlContext;
+import java.security.PrivilegedAction;
-class MethodTypeForm extends MethodTypeImpl {
+public interface JavaSecurityAccess {
+
+ T doIntersectionPrivilege(PrivilegedAction action,
+ AccessControlContext stack,
+ AccessControlContext context);
+
+ T doIntersectionPrivilege(PrivilegedAction action,
+ AccessControlContext context);
- MethodTypeForm(MethodType erasedType) {
- super(erasedType);
- }
}
diff --git a/jdk/src/share/classes/sun/misc/SharedSecrets.java b/jdk/src/share/classes/sun/misc/SharedSecrets.java
index 2335b2d68b5..0bd39b4a5d4 100644
--- a/jdk/src/share/classes/sun/misc/SharedSecrets.java
+++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java
@@ -30,6 +30,8 @@ import java.io.Console;
import java.io.FileDescriptor;
import java.security.ProtectionDomain;
+import java.security.AccessController;
+
/** A repository of "shared secrets", which are a mechanism for
calling implementation-private methods in another package without
using reflection. A package-private class implements a public
@@ -48,6 +50,7 @@ public class SharedSecrets {
private static JavaNioAccess javaNioAccess;
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
+ private static JavaSecurityAccess javaSecurityAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
if (javaUtilJarAccess == null) {
@@ -125,4 +128,15 @@ public class SharedSecrets {
unsafe.ensureClassInitialized(ProtectionDomain.class);
return javaSecurityProtectionDomainAccess;
}
+
+ public static void setJavaSecurityAccess(JavaSecurityAccess jsa) {
+ javaSecurityAccess = jsa;
+ }
+
+ public static JavaSecurityAccess getJavaSecurityAccess() {
+ if (javaSecurityAccess == null) {
+ unsafe.ensureClassInitialized(AccessController.class);
+ }
+ return javaSecurityAccess;
+ }
}
diff --git a/jdk/src/share/classes/sun/net/ResourceManager.java b/jdk/src/share/classes/sun/net/ResourceManager.java
new file mode 100644
index 00000000000..11bfc464819
--- /dev/null
+++ b/jdk/src/share/classes/sun/net/ResourceManager.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 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 sun.net;
+
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * Manages count of total number of UDP sockets and ensures
+ * that exception is thrown if we try to create more than the
+ * configured limit.
+ *
+ * This functionality could be put in NetHooks some time in future.
+ */
+
+public class ResourceManager {
+
+ /* default maximum number of udp sockets per VM
+ * when a security manager is enabled.
+ * The default is 1024 which is high enough to be useful
+ * but low enough to be well below the maximum number
+ * of port numbers actually available on all OSes for
+ * such sockets (5000 on some versions of windows)
+ */
+
+ private static final int DEFAULT_MAX_SOCKETS = 1024;
+ private static final int maxSockets;
+ private static final AtomicInteger numSockets;
+
+ static {
+ String prop = java.security.AccessController.doPrivileged(
+ new GetPropertyAction("sun.net.maxDatagramSockets")
+ );
+ int defmax = DEFAULT_MAX_SOCKETS;
+ try {
+ if (prop != null) {
+ defmax = Integer.parseInt(prop);
+ }
+ } catch (NumberFormatException e) {}
+ maxSockets = defmax;
+ numSockets = new AtomicInteger(0);
+ }
+
+ public static void beforeUdpCreate() throws SocketException {
+ if (System.getSecurityManager() != null) {
+ if (numSockets.incrementAndGet() > maxSockets) {
+ numSockets.decrementAndGet();
+ throw new SocketException("maximum number of DatagramSockets reached");
+ }
+ }
+ }
+
+ public static void afterUdpClose() {
+ if (System.getSecurityManager() != null) {
+ numSockets.decrementAndGet();
+ }
+ }
+}
diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index 69f12a5c601..afc8cea0308 100644
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -2173,6 +2173,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (tryTransparentNTLMServer) {
tryTransparentNTLMServer =
NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
+ /* If the platform supports transparent authentication
+ * then check if we are in a secure environment
+ * whether, or not, we should try transparent authentication.*/
+ if (tryTransparentNTLMServer) {
+ tryTransparentNTLMServer =
+ NTLMAuthenticationProxy.proxy.isTrustedSite(url);
+ }
}
a = null;
if (tryTransparentNTLMServer) {
diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java b/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
index a998d2b1226..b235a0bed17 100644
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
@@ -36,12 +36,14 @@ import sun.util.logging.PlatformLogger;
*/
class NTLMAuthenticationProxy {
private static Method supportsTA;
+ private static Method isTrustedSite;
private static final String clazzStr = "sun.net.www.protocol.http.ntlm.NTLMAuthentication";
private static final String supportsTAStr = "supportsTransparentAuth";
+ private static final String isTrustedSiteStr = "isTrustedSite";
static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
static final boolean supported = proxy != null ? true : false;
- static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false;
+ static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth() : false;
private final Constructor extends AuthenticationInfo> threeArgCtr;
private final Constructor extends AuthenticationInfo> fiveArgCtr;
@@ -82,9 +84,22 @@ class NTLMAuthenticationProxy {
* authentication (try with the current users credentials before
* prompting for username and password, etc).
*/
- private static boolean supportsTransparentAuth(Method method) {
+ private static boolean supportsTransparentAuth() {
try {
- return (Boolean)method.invoke(null);
+ return (Boolean)supportsTA.invoke(null);
+ } catch (ReflectiveOperationException roe) {
+ finest(roe);
+ }
+
+ return false;
+ }
+
+ /* Transparent authentication should only be tried with a trusted
+ * site ( when running in a secure environment ).
+ */
+ public static boolean isTrustedSite(URL url) {
+ try {
+ return (Boolean)isTrustedSite.invoke(null, url);
} catch (ReflectiveOperationException roe) {
finest(roe);
}
@@ -112,6 +127,7 @@ class NTLMAuthenticationProxy {
int.class,
PasswordAuthentication.class);
supportsTA = cl.getDeclaredMethod(supportsTAStr);
+ isTrustedSite = cl.getDeclaredMethod(isTrustedSiteStr, java.net.URL.class);
return new NTLMAuthenticationProxy(threeArg,
fiveArg);
}
diff --git a/jdk/src/share/classes/org/relaxng/datatype/DatatypeException.java b/jdk/src/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java
similarity index 50%
rename from jdk/src/share/classes/org/relaxng/datatype/DatatypeException.java
rename to jdk/src/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java
index aae00d0aa0b..92886311e09 100644
--- a/jdk/src/share/classes/org/relaxng/datatype/DatatypeException.java
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,42 +23,37 @@
* questions.
*/
-package org.relaxng.datatype;
+package sun.net.www.protocol.http.ntlm;
+
+import java.net.URL;
/**
- * Signals Datatype related exceptions.
- *
- * @author James Clark
- * @author Kohsuke KAWAGUCHI
+ * This class is used to call back to deployment to determine if a given
+ * URL is trusted. Transparent authentication (try with logged in users
+ * credentials without prompting) should only be tried with trusted sites.
*/
-public class DatatypeException extends Exception {
+public abstract class NTLMAuthenticationCallback {
+ private static volatile NTLMAuthenticationCallback callback =
+ new DefaultNTLMAuthenticationCallback();
- public DatatypeException( int index, String msg ) {
- super(msg);
- this.index = index;
- }
- public DatatypeException( String msg ) {
- this(UNKNOWN,msg);
- }
- /**
- * A constructor for those datatype libraries which don't support any
- * diagnostic information at all.
- */
- public DatatypeException() {
- this(UNKNOWN,null);
- }
+ public static void setNTLMAuthenticationCallback(
+ NTLMAuthenticationCallback callback) {
+ NTLMAuthenticationCallback.callback = callback;
+ }
+ public static NTLMAuthenticationCallback getNTLMAuthenticationCallback() {
+ return callback;
+ }
- private final int index;
+ /**
+ * Returns true if the given site is trusted, i.e. we can try
+ * transparent Authentication.
+ */
+ public abstract boolean isTrustedSite(URL url);
- public static final int UNKNOWN = -1;
-
- /**
- * Gets the index of the content where the error occured.
- * UNKNOWN can be returned to indicate that no index information
- * is available.
- */
- public int getIndex() {
- return index;
- }
+ static class DefaultNTLMAuthenticationCallback extends NTLMAuthenticationCallback {
+ @Override
+ public boolean isTrustedSite(URL url) { return true; }
+ }
}
+
diff --git a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
index 8d2e31bf74c..de712d6b64f 100644
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
@@ -32,6 +32,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
+import sun.net.ResourceManager;
/**
@@ -101,14 +102,22 @@ class DatagramChannelImpl
throws IOException
{
super(sp);
- this.family = Net.isIPv6Available() ?
- StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
- this.fd = Net.socket(family, false);
- this.fdVal = IOUtil.fdVal(fd);
- this.state = ST_UNCONNECTED;
+ ResourceManager.beforeUdpCreate();
+ try {
+ this.family = Net.isIPv6Available() ?
+ StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
+ this.fd = Net.socket(family, false);
+ this.fdVal = IOUtil.fdVal(fd);
+ this.state = ST_UNCONNECTED;
+ } catch (IOException ioe) {
+ ResourceManager.afterUdpClose();
+ throw ioe;
+ }
}
- public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) {
+ public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
+ throws IOException
+ {
super(sp);
if ((family != StandardProtocolFamily.INET) &&
(family != StandardProtocolFamily.INET6))
@@ -755,11 +764,14 @@ class DatagramChannelImpl
throw new IllegalArgumentException("Group not a multicast address");
// check multicast address is compatible with this socket
- if (!(group instanceof Inet4Address)) {
- if (family == StandardProtocolFamily.INET)
- throw new IllegalArgumentException("Group is not IPv4 address");
- if (!(group instanceof Inet6Address))
- throw new IllegalArgumentException("Address type not supported");
+ if (group instanceof Inet4Address) {
+ if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
+ throw new IllegalArgumentException("Group is not IPv4 multicast address");
+ } else if (group instanceof Inet6Address) {
+ if (family != StandardProtocolFamily.INET6)
+ throw new IllegalArgumentException("Group is not IPv6 multicast address");
+ } else {
+ throw new IllegalArgumentException("Address type not supported");
}
// check source address
@@ -791,7 +803,9 @@ class DatagramChannelImpl
}
MembershipKeyImpl key;
- if (family == StandardProtocolFamily.INET6) {
+ if ((family == StandardProtocolFamily.INET6) &&
+ ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
+ {
int index = interf.getIndex();
if (index == -1)
throw new IOException("Network interface cannot be identified");
@@ -861,7 +875,7 @@ class DatagramChannelImpl
return;
try {
- if (family == StandardProtocolFamily.INET6) {
+ if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
@@ -901,7 +915,7 @@ class DatagramChannelImpl
throw new IllegalArgumentException("Source address is different type to group");
int n;
- if (family == StandardProtocolFamily.INET6) {
+ if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
n = Net.block6(fd, key6.groupAddress(), key6.index(),
@@ -931,7 +945,7 @@ class DatagramChannelImpl
throw new IllegalStateException("key is no longer valid");
try {
- if (family == StandardProtocolFamily.INET6) {
+ if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
Net.unblock6(fd, key6.groupAddress(), key6.index(),
@@ -952,6 +966,7 @@ class DatagramChannelImpl
protected void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
+ ResourceManager.afterUdpClose();
// if member of mulitcast group then invalidate all keys
if (registry != null)
diff --git a/jdk/src/share/classes/sun/nio/ch/Net.java b/jdk/src/share/classes/sun/nio/ch/Net.java
index b1b893a5cb2..58cfe3b1a5b 100644
--- a/jdk/src/share/classes/sun/nio/ch/Net.java
+++ b/jdk/src/share/classes/sun/nio/ch/Net.java
@@ -60,6 +60,21 @@ class Net { // package-private
return isIPv6Available;
}
+ /**
+ * Tells whether IPv6 sockets can join IPv4 multicast groups
+ */
+ static boolean canIPv6SocketJoinIPv4Group() {
+ return canIPv6SocketJoinIPv4Group0();
+ }
+
+ /**
+ * Tells whether {@link #join6} can be used to join an IPv4
+ * multicast group (IPv4 group as IPv4-mapped IPv6 address)
+ */
+ static boolean canJoin6WithIPv4Group() {
+ return canJoin6WithIPv4Group0();
+ }
+
static InetSocketAddress checkAddress(SocketAddress sa) {
if (sa == null)
throw new NullPointerException();
@@ -291,13 +306,18 @@ class Net { // package-private
// -- Socket operations --
- static native boolean isIPv6Available0();
+ private static native boolean isIPv6Available0();
- static FileDescriptor socket(boolean stream) {
+ private static native boolean canIPv6SocketJoinIPv4Group0();
+
+ private static native boolean canJoin6WithIPv4Group0();
+
+ static FileDescriptor socket(boolean stream) throws IOException {
return socket(UNSPEC, stream);
}
- static FileDescriptor socket(ProtocolFamily family, boolean stream) {
+ static FileDescriptor socket(ProtocolFamily family, boolean stream)
+ throws IOException {
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
return IOUtil.newFD(socket0(preferIPv6, stream, false));
diff --git a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java
index 4011291d009..07f931c995c 100644
--- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java
@@ -679,6 +679,14 @@ public class ExtendedCharsets
"1124"
});
+ charset("x-IBM1364", "IBM1364",
+ new String[] {
+ "cp1364",
+ "ibm1364",
+ "ibm-1364",
+ "1364"
+ });
+
charset("IBM273", "IBM273",
new String[] {
"cp273", // JDK historical
diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java
index cd1e6c26b8d..33eeb315f43 100644
--- a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java
@@ -57,8 +57,8 @@ abstract class AbstractAclFileAttributeView
setAcl((List)value);
return;
}
- throw new UnsupportedOperationException("'" + name() + ":" +
- attribute + "' not supported");
+ throw new IllegalArgumentException("'" + name() + ":" +
+ attribute + "' not recognized");
}
@Override
@@ -81,6 +81,8 @@ abstract class AbstractAclFileAttributeView
owner = true;
continue;
}
+ throw new IllegalArgumentException("'" + name() + ":" +
+ attribute + "' not recognized");
}
Map result = new HashMap<>(2);
if (acl)
diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java
index 6383c08edf1..9fa04ee7f8e 100644
--- a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java
@@ -46,6 +46,18 @@ abstract class AbstractBasicFileAttributeView
private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink";
private static final String IS_OTHER_NAME = "isOther";
+ // the names of the basic attributes
+ static final Set basicAttributeNames =
+ Util.newSet(SIZE_NAME,
+ CREATION_TIME_NAME,
+ LAST_ACCESS_TIME_NAME,
+ LAST_MODIFIED_TIME_NAME,
+ FILE_KEY_NAME,
+ IS_DIRECTORY_NAME,
+ IS_REGULAR_FILE_NAME,
+ IS_SYMBOLIC_LINK_NAME,
+ IS_OTHER_NAME);
+
protected AbstractBasicFileAttributeView() { }
@Override
@@ -69,24 +81,26 @@ abstract class AbstractBasicFileAttributeView
setTimes(null, null, (FileTime)value);
return;
}
- throw new UnsupportedOperationException("'" + attribute +
- "' is unknown or read-only attribute");
+ throw new IllegalArgumentException("'" + name() + ":" +
+ attribute + "' not recognized");
}
/**
* Used to build a map of attribute name/values.
*/
static class AttributesBuilder {
- private Set set = new HashSet<>();
+ private Set names = new HashSet<>();
private Map map = new HashMap<>();
private boolean copyAll;
- private AttributesBuilder(String[] attributes) {
- for (String attribute: attributes) {
- if (attribute.equals("*")) {
+ private AttributesBuilder(Set allowed, String[] requested) {
+ for (String name: requested) {
+ if (name.equals("*")) {
copyAll = true;
} else {
- set.add(attribute);
+ if (!allowed.contains(name))
+ throw new IllegalArgumentException("'" + name + "' not recognized");
+ names.add(name);
}
}
}
@@ -94,21 +108,19 @@ abstract class AbstractBasicFileAttributeView
/**
* Creates builder to build up a map of the matching attributes
*/
- static AttributesBuilder create(String[] attributes) {
- return new AttributesBuilder(attributes);
+ static AttributesBuilder create(Set allowed, String[] requested) {
+ return new AttributesBuilder(allowed, requested);
}
/**
* Returns true if the attribute should be returned in the map
*/
- boolean match(String attribute) {
- if (copyAll)
- return true;
- return set.contains(attribute);
+ boolean match(String name) {
+ return copyAll || names.contains(name);
}
- void add(String attribute, Object value) {
- map.put(attribute, value);
+ void add(String name, Object value) {
+ map.put(name, value);
}
/**
@@ -124,7 +136,7 @@ abstract class AbstractBasicFileAttributeView
* Invoked by readAttributes or sub-classes to add all matching basic
* attributes to the builder
*/
- final void addBasicAttributesToBuilder(BasicFileAttributes attrs,
+ final void addRequestedBasicAttributes(BasicFileAttributes attrs,
AttributesBuilder builder)
{
if (builder.match(SIZE_NAME))
@@ -148,9 +160,12 @@ abstract class AbstractBasicFileAttributeView
}
@Override
- public Map readAttributes(String[] attributes) throws IOException {
- AttributesBuilder builder = AttributesBuilder.create(attributes);
- addBasicAttributesToBuilder(readAttributes(), builder);
+ public Map readAttributes(String[] requested)
+ throws IOException
+ {
+ AttributesBuilder builder =
+ AttributesBuilder.create(basicAttributeNames, requested);
+ addRequestedBasicAttributes(readAttributes(), builder);
return builder.unmodifiableMap();
}
}
diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
index 95d1cb30931..9e1dc6133ac 100644
--- a/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
@@ -29,7 +29,6 @@ import java.nio.file.*;
import java.nio.file.spi.FileSystemProvider;
import java.io.IOException;
import java.util.Map;
-import java.util.Collections;
/**
* Base implementation class of FileSystemProvider
@@ -72,6 +71,8 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider {
throws IOException
{
String[] s = split(attribute);
+ if (s[0].length() == 0)
+ throw new IllegalArgumentException(attribute);
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
if (view == null)
throw new UnsupportedOperationException("View '" + s[0] + "' not available");
@@ -83,9 +84,11 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider {
throws IOException
{
String[] s = split(attributes);
+ if (s[0].length() == 0)
+ throw new IllegalArgumentException(attributes);
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
if (view == null)
- return Collections.emptyMap();
+ throw new UnsupportedOperationException("View '" + s[0] + "' not available");
return view.readAttributes(s[1].split(","));
}
diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
index cf36a09ff0a..8a4f975c4f4 100644
--- a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
@@ -59,22 +59,6 @@ abstract class AbstractUserDefinedFileAttributeView
return "user";
}
- private Object getAttribute(String attribute) throws IOException {
- int size;
- try {
- size = size(attribute);
- } catch (IOException e) {
- // not found or some other I/O error
- if (list().contains(attribute))
- throw e;
- return null;
- }
-
- byte[] buf = new byte[size];
- int n = read(attribute, ByteBuffer.wrap(buf));
- return (n == size) ? buf : Arrays.copyOf(buf, n);
- }
-
@Override
public final void setAttribute(String attribute, Object value)
throws IOException
@@ -94,12 +78,13 @@ abstract class AbstractUserDefinedFileAttributeView
{
// names of attributes to return
List names = new ArrayList<>();
-
for (String name: attributes) {
if (name.equals("*")) {
names = list();
break;
} else {
+ if (name.length() == 0)
+ throw new IllegalArgumentException();
names.add(name);
}
}
@@ -107,11 +92,12 @@ abstract class AbstractUserDefinedFileAttributeView
// read each value and return in map
Map result = new HashMap<>();
for (String name: names) {
- Object value = getAttribute(name);
- if (value != null)
- result.put(name, value);
+ int size = size(name);
+ byte[] buf = new byte[size];
+ int n = read(name, ByteBuffer.wrap(buf));
+ byte[] value = (n == size) ? buf : Arrays.copyOf(buf, n);
+ result.put(name, value);
}
-
return result;
}
}
diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java
index 55234ba6528..f083f46313a 100644
--- a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java
@@ -81,7 +81,8 @@ abstract class AbstractWatchKey implements WatchKey {
/**
* Return the original watchable (Path)
*/
- Path watchable() {
+ @Override
+ public Path watchable() {
return dir;
}
diff --git a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java
index aae9bd318c1..5fcb21e264a 100644
--- a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java
+++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java
@@ -63,10 +63,10 @@ final class FileOwnerAttributeViewImpl
{
if (attribute.equals(OWNER_NAME)) {
setOwner((UserPrincipal)value);
- return;
+ } else {
+ throw new IllegalArgumentException("'" + name() + ":" +
+ attribute + "' not recognized");
}
- throw new UnsupportedOperationException("'" + name() + ":" +
- attribute + "' not supported");
}
@Override
@@ -75,6 +75,9 @@ final class FileOwnerAttributeViewImpl
for (String attribute: attributes) {
if (attribute.equals("*") || attribute.equals(OWNER_NAME)) {
result.put(OWNER_NAME, getOwner());
+ } else {
+ throw new IllegalArgumentException("'" + name() + ":" +
+ attribute + "' not recognized");
}
}
return result;
diff --git a/jdk/src/share/classes/sun/nio/fs/Util.java b/jdk/src/share/classes/sun/nio/fs/Util.java
index 6a289058e4b..76287011169 100644
--- a/jdk/src/share/classes/sun/nio/fs/Util.java
+++ b/jdk/src/share/classes/sun/nio/fs/Util.java
@@ -25,6 +25,8 @@
package sun.nio.fs;
+import java.util.*;
+
/**
* Utility methods
*/
@@ -54,6 +56,28 @@ class Util {
}
result[n] = s.substring(last, s.length());
return result;
+ }
+ /**
+ * Returns a Set containing the given elements.
+ */
+ static Set newSet(E... elements) {
+ HashSet set = new HashSet<>();
+ for (E e: elements) {
+ set.add(e);
+ }
+ return set;
+ }
+
+ /**
+ * Returns a Set containing all the elements of the given Set plus
+ * the given elements.
+ */
+ static Set newSet(Set other, E... elements) {
+ HashSet set = new HashSet<>(other);
+ for (E e: elements) {
+ set.add(e);
+ }
+ return set;
}
}
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
index b54d0d3c190..56c40a97586 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java
@@ -999,18 +999,34 @@ abstract class P11Key implements Key {
new CK_ATTRIBUTE(CKA_EC_PARAMS),
};
fetchAttributes(attributes);
+
try {
params = P11ECKeyFactory.decodeParameters
(attributes[1].getByteArray());
- DerValue wECPoint = new DerValue(attributes[0].getByteArray());
- if (wECPoint.getTag() != DerValue.tag_OctetString)
- throw new IOException("Unexpected tag: " +
- wECPoint.getTag());
- params = P11ECKeyFactory.decodeParameters
- (attributes[1].getByteArray());
- w = P11ECKeyFactory.decodePoint
- (wECPoint.getDataBytes(), params.getCurve());
+ /*
+ * An uncompressed EC point may be in either of two formats.
+ * First try the OCTET STRING encoding:
+ * 04 04
+ *
+ * Otherwise try the raw encoding:
+ * 04
+ */
+ byte[] ecKey = attributes[0].getByteArray();
+
+ try {
+ DerValue wECPoint = new DerValue(ecKey);
+ if (wECPoint.getTag() != DerValue.tag_OctetString)
+ throw new IOException("Unexpected tag: " +
+ wECPoint.getTag());
+
+ w = P11ECKeyFactory.decodePoint
+ (wECPoint.getDataBytes(), params.getCurve());
+
+ } catch (IOException e) {
+ // Failover
+ w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve());
+ }
} catch (Exception e) {
throw new RuntimeException("Could not parse key values", e);
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java b/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java
index 1b14bf8fa66..959ac59d12c 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java
@@ -46,10 +46,16 @@ import sun.security.x509.AuthorityKeyIdentifierExtension;
*/
class AdaptableX509CertSelector extends X509CertSelector {
// The start date of a validity period.
- private Date startDate = null;
+ private Date startDate;
// The end date of a validity period.
- private Date endDate = null;
+ private Date endDate;
+
+ // Is subject key identifier sensitive?
+ private boolean isSKIDSensitive = false;
+
+ // Is serial number sensitive?
+ private boolean isSNSensitive = false;
AdaptableX509CertSelector() {
super();
@@ -97,15 +103,24 @@ class AdaptableX509CertSelector extends X509CertSelector {
if (akidext != null) {
KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID);
if (akid != null) {
- DerOutputStream derout = new DerOutputStream();
- derout.putOctetString(akid.getIdentifier());
- super.setSubjectKeyIdentifier(derout.toByteArray());
+ // Do not override the previous setting for initial selection.
+ if (isSKIDSensitive || getSubjectKeyIdentifier() == null) {
+ DerOutputStream derout = new DerOutputStream();
+ derout.putOctetString(akid.getIdentifier());
+ super.setSubjectKeyIdentifier(derout.toByteArray());
+
+ isSKIDSensitive = true;
+ }
}
SerialNumber asn =
(SerialNumber)akidext.get(akidext.SERIAL_NUMBER);
if (asn != null) {
- super.setSerialNumber(asn.getNumber());
+ // Do not override the previous setting for initial selection.
+ if (isSNSensitive || getSerialNumber() == null) {
+ super.setSerialNumber(asn.getNumber());
+ isSNSensitive = true;
+ }
}
// the subject criterion should be set by the caller.
@@ -148,11 +163,25 @@ class AdaptableX509CertSelector extends X509CertSelector {
}
}
- if (version < 3 || xcert.getExtensionValue("2.5.29.14") == null) {
- // If no SubjectKeyIdentifier extension, don't bother to check it.
+ // If no SubjectKeyIdentifier extension, don't bother to check it.
+ if (isSKIDSensitive &&
+ (version < 3 || xcert.getExtensionValue("2.5.29.14") == null)) {
setSubjectKeyIdentifier(null);
}
+ // In practice, a CA may replace its root certificate and require that
+ // the existing certificate is still valid, even if the AKID extension
+ // does not match the replacement root certificate fields.
+ //
+ // Conservatively, we only support the replacement for version 1 and
+ // version 2 certificate. As for version 2, the certificate extension
+ // may contain sensitive information (for example, policies), the
+ // AKID need to be respected to seek the exact certificate in case
+ // of key or certificate abuse.
+ if (isSNSensitive && version < 3) {
+ setSerialNumber(null);
+ }
+
return super.match(cert);
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
index e9c0ca77879..e2666a6771b 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
@@ -243,12 +243,6 @@ class ForwardBuilder extends Builder {
caTargetSelector.setPolicy(getMatchingPolicies());
}
- /*
- * Require CA certs with a pathLenConstraint that allows
- * at least as many CA certs that have already been traversed
- */
- caTargetSelector.setBasicConstraints(currentState.traversedCACerts);
-
sel = caTargetSelector;
} else {
@@ -282,12 +276,6 @@ class ForwardBuilder extends Builder {
CertPathHelper.setPathToNames
(caSelector, currentState.subjectNamesTraversed);
- /*
- * Require CA certs with a pathLenConstraint that allows
- * at least as many CA certs that have already been traversed
- */
- caSelector.setBasicConstraints(currentState.traversedCACerts);
-
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
@@ -305,6 +293,14 @@ class ForwardBuilder extends Builder {
sel = caSelector;
}
+ /*
+ * For compatibility, conservatively, we don't check the path
+ * length constraint of trusted anchors. Please don't set the
+ * basic constraints criterion unless the trusted certificate
+ * matching is completed.
+ */
+ sel.setBasicConstraints(-1);
+
for (X509Certificate trustedCert : trustedCerts) {
if (sel.match(trustedCert)) {
if (debug != null) {
@@ -323,6 +319,12 @@ class ForwardBuilder extends Builder {
*/
sel.setCertificateValid(date);
+ /*
+ * Require CA certs with a pathLenConstraint that allows
+ * at least as many CA certs that have already been traversed
+ */
+ sel.setBasicConstraints(currentState.traversedCACerts);
+
/*
* If we have already traversed as many CA certs as the maxPathLength
* will allow us to, then we don't bother looking through these
diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
index 3920b35c37a..fbf23196aba 100644
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, 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
@@ -377,8 +377,9 @@ final class ClientHandshaker extends Handshaker {
ProtocolVersion mesgVersion = mesg.protocolVersion;
if (!isNegotiable(mesgVersion)) {
throw new SSLHandshakeException(
- "Server chose unsupported or disabled protocol: " +
- mesgVersion);
+ "Server chose " + mesgVersion +
+ ", but that protocol version is not enabled or not supported " +
+ "by the client.");
}
handshakeHash.protocolDetermined(mesgVersion);
diff --git a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java
index 1668e6ff79d..bba258670d8 100644
--- a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java
+++ b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -195,6 +195,8 @@ public abstract class SunJSSE extends java.security.Provider {
"sun.security.ssl.KeyManagerFactoryImpl$SunX509");
put("KeyManagerFactory.NewSunX509",
"sun.security.ssl.KeyManagerFactoryImpl$X509");
+ put("Alg.Alias.KeyManagerFactory.PKIX", "NewSunX509");
+
put("TrustManagerFactory.SunX509",
"sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
put("TrustManagerFactory.PKIX",
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
index a5c73549809..0016ae24d20 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Pierre & Miquelon Standard Time", "PMST",
"Pierre & Miquelon Daylight Time", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java
index b3cb23224fa..0e4d91d94f7 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Pierre & Miquelon Normalzeit", "PMST",
"Pierre & Miquelon Sommerzeit", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java
index 613cc6419fb..711afc45563 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Hora est\u00e1ndar de Pierre & Miquelon", "PMST",
"Hora de verano de Pierre & Miquelon", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java
index f1dc5300c25..090820b6742 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Heure normale de Saint-Pierre et Miquelon", "PMST",
"Heure avanc\u00e9e de Saint-Pierre et Miquelon", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java
index e983872e7a1..6413104ba74 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Ora solare di Saint-Pierre e Miquelon", "PMST",
"Ora legale di Saint-Pierre e Miquelon", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java
index 56330acf91d..4c1226666c8 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u6a19\u6e96\u6642", "PMST",
"\u30b5\u30f3\u30d4\u30a8\u30fc\u30eb\u30fb\u30df\u30af\u30ed\u30f3\u8af8\u5cf6\u590f\u6642\u9593", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java
index 82edcce1ec5..486e1bdd9a5 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \ud45c\uc900\uc2dc", "PMST",
"\ud53c\uc5d0\ub974 \ubbf8\ud06c\ub860 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java
index d9b83fe0491..7eab4bb48b4 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java
@@ -217,6 +217,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Fuso hor\u00e1rio padr\u00e3o de S\u00e3o Pedro e Miquelon", "PMST",
"Hor\u00e1rio de luz natural de S\u00e3o Pedro e Miquelon", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java
index 14108065241..63b5e084523 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"Saint-Pierre-et-Miquelon, normaltid", "PMST",
"Saint-Pierre-et-Miquelon, sommartid", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java
index 4f80a1b739c..b215a186e9a 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u6807\u51c6\u65f6\u95f4", "PMST",
"\u76ae\u57c3\u5c14\u5c9b\u53ca\u5bc6\u514b\u9686\u5c9b\u590f\u4ee4\u65f6", "PMDT"}},
diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java
index 5218bed7ed6..7a638641e89 100644
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java
+++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java
@@ -216,6 +216,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"America/Anchorage", AKST},
{"AST", AKST},
{"America/Halifax", AST},
+ {"America/Sitka", AKST},
{"America/St_Johns", NST},
{"CNT", NST},
{"Europe/Paris", CET},
@@ -392,6 +393,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"America/Mendoza", AGT},
{"America/Menominee", CST},
{"America/Merida", CST},
+ {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST",
+ "Metlakatla Daylight Time", "MeDT"}},
{"America/Mexico_City", CST},
{"America/Miquelon", new String[] {"\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u6a19\u6e96\u6642\u9593", "PMST",
"\u76ae\u57c3\u723e\u5cf6\u53ca\u5bc6\u514b\u9686\u5cf6\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PMDT"}},
diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security
index 5a0726de0a7..a89d40e194b 100644
--- a/jdk/src/share/lib/security/java.security
+++ b/jdk/src/share/lib/security/java.security
@@ -123,7 +123,7 @@ keystore.type=jks
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.imageio.
+package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.
#
# List of comma-separated packages that start with or equal this string
diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris
index 8e9b1ffd791..1a19f44d231 100644
--- a/jdk/src/share/lib/security/java.security-solaris
+++ b/jdk/src/share/lib/security/java.security-solaris
@@ -124,7 +124,7 @@ keystore.type=jks
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.imageio.
+package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.
#
# List of comma-separated packages that start with or equal this string
diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows
index 99eda51b910..3db627a4f32 100644
--- a/jdk/src/share/lib/security/java.security-windows
+++ b/jdk/src/share/lib/security/java.security-windows
@@ -124,7 +124,7 @@ keystore.type=jks
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.imageio.
+package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.
#
# List of comma-separated packages that start with or equal this string
diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
index b53b14ed87b..40067b1df0f 100644
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp
@@ -489,7 +489,6 @@ enum { CHUNK = (1 << 14), SMALL = (1 << 9) };
// Call malloc. Try to combine small blocks and free much later.
void* unpacker::alloc_heap(size_t size, bool smallOK, bool temp) {
- CHECK_0;
if (!smallOK || size > SMALL) {
void* res = must_malloc((int)size);
(temp ? &tmallocs : &mallocs)->add(res);
@@ -2560,6 +2559,10 @@ void unpacker::putlayout(band** body) {
int i;
int prevBII = -1;
int prevBCI = -1;
+ if (body == NULL) {
+ abort("putlayout: unexpected NULL for body");
+ return;
+ }
for (i = 0; body[i] != null; i++) {
band& b = *body[i];
byte le_kind = b.le_kind;
@@ -4767,7 +4770,9 @@ void unpacker::redirect_stdio() {
}
char *tname = tempnam(tmpdir,"#upkg");
+ if (tname == NULL) return;
sprintf(log_file_name, "%s", tname);
+ ::free(tname);
if ((errstrm = fopen(log_file_name, "a+")) != NULL) {
log_file = errstrm_name = saveStr(log_file_name);
return ;
diff --git a/jdk/src/share/native/com/sun/media/sound/SoundDefs.h b/jdk/src/share/native/com/sun/media/sound/SoundDefs.h
index 5ac73451681..f141ea62ac2 100644
--- a/jdk/src/share/native/com/sun/media/sound/SoundDefs.h
+++ b/jdk/src/share/native/com/sun/media/sound/SoundDefs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2011, 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
@@ -39,6 +39,8 @@
#define X_IA64 4
#define X_AMD64 5
#define X_ZERO 6
+#define X_ARM 7
+#define X_PPC 8
// **********************************
// Make sure you set X_PLATFORM and X_ARCH defines correctly.
diff --git a/jdk/src/share/native/common/check_code.c b/jdk/src/share/native/common/check_code.c
index 00dcdf163b3..dcdaeda58bf 100644
--- a/jdk/src/share/native/common/check_code.c
+++ b/jdk/src/share/native/common/check_code.c
@@ -2685,11 +2685,11 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta
switch (type_table[operand]) {
case JVM_CONSTANT_MethodType:
full_info = make_class_info_from_name(context,
- "java/dyn/MethodType");
+ "java/lang/invoke/MethodType");
break;
default: //JVM_CONSTANT_MethodHandle
full_info = make_class_info_from_name(context,
- "java/dyn/MethodHandle");
+ "java/lang/invoke/MethodHandle");
break;
}
break;
diff --git a/jdk/src/share/native/java/lang/fdlibm/include/fdlibm.h b/jdk/src/share/native/java/lang/fdlibm/include/fdlibm.h
index 2b3592dc143..196bb0d8e02 100644
--- a/jdk/src/share/native/java/lang/fdlibm/include/fdlibm.h
+++ b/jdk/src/share/native/java/lang/fdlibm/include/fdlibm.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, 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
@@ -28,8 +28,8 @@
#ifdef __NEWVALID /* special setup for Sun test regime */
#if defined(i386) || defined(i486) || \
- defined(intel) || defined(x86) || \
- defined(i86pc) || defined(_M_IA64) || defined(ia64)
+ defined(intel) || defined(x86) || defined(arm) || \
+ defined(i86pc) || defined(_M_IA64) || defined(ia64)
#define _LITTLE_ENDIAN
#endif
#endif
diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
index 04a87fd1cac..84b91889725 100644
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
@@ -40,7 +40,7 @@
#include
#include
#include
-
+#include
/* java native interface headers */
#include "jni.h"
@@ -2657,7 +2657,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage
(destWidth < 0) || (destWidth > srcWidth) ||
(destHeight < 0) ||
(stepX < 0) || (stepY < 0) ||
- ((scanLineSize / numBands) < destWidth)) /* destWidth causes an integer overflow */
+ ((INT_MAX / numBands) < destWidth)) /* destWidth causes an integer overflow */
{
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid argument to native writeImage");
diff --git a/jdk/src/share/native/sun/font/layout/KernTable.cpp b/jdk/src/share/native/sun/font/layout/KernTable.cpp
index 8d368211309..3a9987eb6b9 100644
--- a/jdk/src/share/native/sun/font/layout/KernTable.cpp
+++ b/jdk/src/share/native/sun/font/layout/KernTable.cpp
@@ -210,7 +210,7 @@ void KernTable::process(LEGlyphStorage& storage)
// all the elements ahead of time and store them in the font
const PairInfo* p = pairs;
- const PairInfo* tp = (const PairInfo*)(p + rangeShift);
+ const PairInfo* tp = (const PairInfo*)(p + (rangeShift/KERN_PAIRINFO_SIZE)); /* rangeshift is in original table bytes */
if (key > tp->key) {
p = tp;
}
@@ -222,7 +222,7 @@ void KernTable::process(LEGlyphStorage& storage)
le_uint32 probe = searchRange;
while (probe > 1) {
probe >>= 1;
- tp = (const PairInfo*)(p + probe);
+ tp = (const PairInfo*)(p + (probe/KERN_PAIRINFO_SIZE));
le_uint32 tkey = tp->key;
#if DEBUG
fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairs), tkey);
diff --git a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp
index 6b0aa1baa58..90aafde2a80 100644
--- a/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp
+++ b/jdk/src/share/native/sun/font/layout/LayoutEngine.cpp
@@ -251,6 +251,10 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
return 0;
}
+ if ((fTypoFlags & 0x4) == 0) { // no canonical processing
+ return count;
+ }
+
const GlyphSubstitutionTableHeader *canonGSUBTable = (GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
diff --git a/jdk/src/share/native/sun/java2d/loops/ProcessPath.c b/jdk/src/share/native/sun/java2d/loops/ProcessPath.c
index b4f724752dc..5131a3e22c7 100644
--- a/jdk/src/share/native/sun/java2d/loops/ProcessPath.c
+++ b/jdk/src/share/native/sun/java2d/loops/ProcessPath.c
@@ -118,19 +118,25 @@
jint Y1 = (fY1) >> MDP_PREC; \
jint res; \
\
- /* Checking bounds and clipping if necessary */ \
+ /* Checking bounds and clipping if necessary. \
+ * REMIND: It's temporary solution to avoid OOB in rendering code. \
+ * Current approach uses float equations which are unreliable for \
+ * clipping and makes assumptions about the line biases of the \
+ * rendering algorithm. Also, clipping code should be moved down \
+ * into only those output renderers that need it. \
+ */ \
if (checkBounds) { \
- TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y0, X0, Y1, X1, \
- jint, res); \
+ jfloat xMinf = hnd->dhnd->xMinf + 0.5f; \
+ jfloat yMinf = hnd->dhnd->yMinf + 0.5f; \
+ jfloat xMaxf = hnd->dhnd->xMaxf + 0.5f; \
+ jfloat yMaxf = hnd->dhnd->yMaxf + 0.5f; \
+ TESTANDCLIP(yMinf, yMaxf, Y0, X0, Y1, X1, jint, res); \
if (res == CRES_INVISIBLE) break; \
- TESTANDCLIP(hnd->dhnd->yMin, hnd->dhnd->yMax, Y1, X1, Y0, X0, \
- jint, res); \
+ TESTANDCLIP(yMinf, yMaxf, Y1, X1, Y0, X0, jint, res); \
if (res == CRES_INVISIBLE) break; \
- TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X0, Y0, X1, Y1, \
- jint, res); \
+ TESTANDCLIP(xMinf, xMaxf, X0, Y0, X1, Y1, jint, res); \
if (res == CRES_INVISIBLE) break; \
- TESTANDCLIP(hnd->dhnd->xMin, hnd->dhnd->xMax, X1, Y1, X0, Y0, \
- jint, res); \
+ TESTANDCLIP(xMinf, xMaxf, X1, Y1, X0, Y0, jint, res); \
if (res == CRES_INVISIBLE) break; \
} \
\
diff --git a/jdk/src/share/sample/nio/file/WatchDir.java b/jdk/src/share/sample/nio/file/WatchDir.java
index 33c15dd0c04..796b728206b 100644
--- a/jdk/src/share/sample/nio/file/WatchDir.java
+++ b/jdk/src/share/sample/nio/file/WatchDir.java
@@ -33,8 +33,7 @@ import java.nio.file.*;
import static java.nio.file.StandardWatchEventKind.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
-import java.io.*;
-import java.util.*;
+import java.io.IOException;
/**
* Example to watch a directory (or tree) for changes to files.
@@ -43,9 +42,9 @@ import java.util.*;
public class WatchDir {
private final WatchService watcher;
- private final Map keys;
private final boolean recursive;
private boolean trace = false;
+ private int count;
@SuppressWarnings("unchecked")
static WatchEvent cast(WatchEvent> event) {
@@ -57,17 +56,9 @@ public class WatchDir {
*/
private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
- if (trace) {
- Path prev = keys.get(key);
- if (prev == null) {
- System.out.format("register: %s\n", dir);
- } else {
- if (!dir.equals(prev)) {
- System.out.format("update: %s -> %s\n", prev, dir);
- }
- }
- }
- keys.put(key, dir);
+ count++;
+ if (trace)
+ System.out.format("register: %s\n", dir);
}
/**
@@ -92,7 +83,6 @@ public class WatchDir {
*/
WatchDir(Path dir, boolean recursive) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
- this.keys = new HashMap();
this.recursive = recursive;
if (recursive) {
@@ -121,12 +111,6 @@ public class WatchDir {
return;
}
- Path dir = keys.get(key);
- if (dir == null) {
- System.err.println("WatchKey not recognized!!");
- continue;
- }
-
for (WatchEvent> event: key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
@@ -138,7 +122,7 @@ public class WatchDir {
// Context for directory entry event is the file name of entry
WatchEvent ev = cast(event);
Path name = ev.context();
- Path child = dir.resolve(name);
+ Path child = ((Path)key.watchable()).resolve(name);
// print out event
System.out.format("%s: %s\n", event.kind().name(), child);
@@ -156,15 +140,13 @@ public class WatchDir {
}
}
- // reset key and remove from set if directory no longer accessible
+ // reset key
boolean valid = key.reset();
if (!valid) {
- keys.remove(key);
-
- // all directories are inaccessible
- if (keys.isEmpty()) {
+ // directory no longer accessible
+ count--;
+ if (count == 0)
break;
- }
}
}
}
diff --git a/jdk/src/solaris/bin/ergo.c b/jdk/src/solaris/bin/ergo.c
index e9e863e9ce5..2047087e7c5 100644
--- a/jdk/src/solaris/bin/ergo.c
+++ b/jdk/src/solaris/bin/ergo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, 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
@@ -67,6 +67,35 @@ ServerClassMachine(void) {
}
}
+#ifdef USE_GENERIC_ERGO
+/* Ask the OS how many processors there are. */
+static unsigned long
+physical_processors(void) {
+ const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+ JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+ return sys_processors;
+}
+
+jboolean
+ServerClassMachineImpl(void) {
+ jboolean result = JNI_FALSE;
+ /* How big is a server class machine? */
+ const unsigned long server_processors = 2UL;
+ const uint64_t server_memory = 2UL * GB;
+ const uint64_t actual_memory = physical_memory();
+
+ /* Is this a server class machine? */
+ if (actual_memory >= server_memory) {
+ const unsigned long actual_processors = physical_processors();
+ if (actual_processors >= server_processors) {
+ result = JNI_TRUE;
+ }
+ }
+ JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
+ (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
+ return result;
+}
+#endif
/* Compute physical memory by asking the OS */
uint64_t
diff --git a/jdk/src/solaris/bin/ergo_sparc.c b/jdk/src/solaris/bin/ergo_sparc.c
deleted file mode 100644
index 9261a423de6..00000000000
--- a/jdk/src/solaris/bin/ergo_sparc.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.
- */
-#include "ergo.h"
-
-
-/* Methods for solaris-sparc and linux-sparc: these are easy. */
-
-/* Ask the OS how many processors there are. */
-static unsigned long
-physical_processors(void) {
- const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-
- JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
- return sys_processors;
-}
-
-/* The sparc version of the "server-class" predicate. */
-jboolean
-ServerClassMachineImpl(void) {
- jboolean result = JNI_FALSE;
- /* How big is a server class machine? */
- const unsigned long server_processors = 2UL;
- const uint64_t server_memory = 2UL * GB;
- const uint64_t actual_memory = physical_memory();
-
- /* Is this a server class machine? */
- if (actual_memory >= server_memory) {
- const unsigned long actual_processors = physical_processors();
- if (actual_processors >= server_processors) {
- result = JNI_TRUE;
- }
- }
- JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
- (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
- return result;
-}
diff --git a/jdk/src/solaris/bin/ergo_zero.c b/jdk/src/solaris/bin/ergo_zero.c
deleted file mode 100644
index 9261a423de6..00000000000
--- a/jdk/src/solaris/bin/ergo_zero.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 1998, 2007, 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.
- */
-#include "ergo.h"
-
-
-/* Methods for solaris-sparc and linux-sparc: these are easy. */
-
-/* Ask the OS how many processors there are. */
-static unsigned long
-physical_processors(void) {
- const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
-
- JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
- return sys_processors;
-}
-
-/* The sparc version of the "server-class" predicate. */
-jboolean
-ServerClassMachineImpl(void) {
- jboolean result = JNI_FALSE;
- /* How big is a server class machine? */
- const unsigned long server_processors = 2UL;
- const uint64_t server_memory = 2UL * GB;
- const uint64_t actual_memory = physical_memory();
-
- /* Is this a server class machine? */
- if (actual_memory >= server_memory) {
- const unsigned long actual_processors = physical_processors();
- if (actual_processors >= server_processors) {
- result = JNI_TRUE;
- }
- }
- JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
- (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
- return result;
-}
diff --git a/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 5ad8b8d54d8..be2426d7f72 100644
--- a/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/jdk/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -68,6 +68,9 @@ import sun.net.www.protocol.http.HttpURLConnection;
public class NTLMAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 170L;
+ private static final NTLMAuthenticationCallback NTLMAuthCallback =
+ NTLMAuthenticationCallback.getNTLMAuthenticationCallback();
+
private String hostname;
private static String defaultDomain; /* Domain to use if not specified by user */
@@ -81,6 +84,14 @@ public class NTLMAuthentication extends AuthenticationInfo {
return false;
}
+ /**
+ * Returns true if the given site is trusted, i.e. we can try
+ * transparent Authentication.
+ */
+ public static boolean isTrustedSite(URL url) {
+ return NTLMAuthCallback.isTrustedSite(url);
+ }
+
private void init0() {
hostname = java.security.AccessController.doPrivileged(
diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
index 4499a08924c..af0dc1036bd 100644
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
@@ -27,6 +27,7 @@ package sun.nio.fs;
import java.nio.file.attribute.*;
import java.util.Map;
+import java.util.Set;
import java.io.IOException;
import sun.misc.Unsafe;
@@ -57,6 +58,10 @@ class LinuxDosFileAttributeView
private static final int DOS_XATTR_SYSTEM = 0x04;
private static final int DOS_XATTR_ARCHIVE = 0x20;
+ // the names of the DOS attributes (includes basic)
+ private static final Set dosAttributeNames =
+ Util.newSet(basicAttributeNames, READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME);
+
LinuxDosFileAttributeView(UnixPath file, boolean followLinks) {
super(file, followLinks);
}
@@ -93,9 +98,10 @@ class LinuxDosFileAttributeView
public Map readAttributes(String[] attributes)
throws IOException
{
- AttributesBuilder builder = AttributesBuilder.create(attributes);
+ AttributesBuilder builder =
+ AttributesBuilder.create(dosAttributeNames, attributes);
DosFileAttributes attrs = readAttributes();
- addBasicAttributesToBuilder(attrs, builder);
+ addRequestedBasicAttributes(attrs, builder);
if (builder.match(READONLY_NAME))
builder.add(READONLY_NAME, attrs.isReadOnly());
if (builder.match(ARCHIVE_NAME))
diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
index b8b8c30f936..18309cb4450 100644
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
@@ -28,8 +28,6 @@ package sun.nio.fs;
import java.nio.file.*;
import java.io.IOException;
import java.util.*;
-import java.security.AccessController;
-import sun.security.action.GetPropertyAction;
import static sun.nio.fs.LinuxNativeDispatcher.*;
/**
@@ -37,42 +35,16 @@ import static sun.nio.fs.LinuxNativeDispatcher.*;
*/
class LinuxFileSystem extends UnixFileSystem {
- private final boolean hasInotify;
-
LinuxFileSystem(UnixFileSystemProvider provider, String dir) {
super(provider, dir);
-
- // assume X.Y[-Z] format
- String osversion = AccessController
- .doPrivileged(new GetPropertyAction("os.version"));
- String[] vers = Util.split(osversion, '.');
- assert vers.length >= 2;
-
- int majorVersion = Integer.parseInt(vers[0]);
- int minorVersion = Integer.parseInt(vers[1]);
- int microVersion = 0;
- if (vers.length > 2) {
- String[] microVers = Util.split(vers[2], '-');
- microVersion = (microVers.length > 0) ?
- Integer.parseInt(microVers[0]) : 0;
- }
-
- // inotify available since 2.6.13
- this.hasInotify = ((majorVersion > 2) ||
- (majorVersion == 2 && minorVersion > 6) ||
- ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13)));
}
@Override
public WatchService newWatchService()
throws IOException
{
- if (hasInotify) {
- return new LinuxWatchService(this);
- } else {
- // use polling implementation on older kernels
- return new PollingWatchService();
- }
+ // assume 2.6.13 or newer
+ return new LinuxWatchService(this);
}
diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java
index c21a17707a8..ad0a2a00d12 100644
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java
@@ -123,6 +123,10 @@ class UnixFileAttributeViews {
private static final String OWNER_NAME = "owner";
private static final String GROUP_NAME = "group";
+ // the names of the posix attributes (incudes basic)
+ static final Set posixAttributeNames =
+ Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME);
+
Posix(UnixPath file, boolean followLinks) {
super(file, followLinks);
}
@@ -172,9 +176,10 @@ class UnixFileAttributeViews {
* Invoked by readAttributes or sub-classes to add all matching posix
* attributes to the builder
*/
- final void addPosixAttributesToBuilder(PosixFileAttributes attrs,
+ final void addRequestedPosixAttributes(PosixFileAttributes attrs,
AttributesBuilder builder)
{
+ addRequestedBasicAttributes(attrs, builder);
if (builder.match(PERMISSIONS_NAME))
builder.add(PERMISSIONS_NAME, attrs.permissions());
if (builder.match(OWNER_NAME))
@@ -184,13 +189,13 @@ class UnixFileAttributeViews {
}
@Override
- public Map readAttributes(String[] attributes)
+ public Map readAttributes(String[] requested)
throws IOException
{
- AttributesBuilder builder = AttributesBuilder.create(attributes);
+ AttributesBuilder builder =
+ AttributesBuilder.create(posixAttributeNames, requested);
PosixFileAttributes attrs = readAttributes();
- addBasicAttributesToBuilder(attrs, builder);
- addPosixAttributesToBuilder(attrs, builder);
+ addRequestedPosixAttributes(attrs, builder);
return builder.unmodifiableMap();
}
@@ -287,6 +292,12 @@ class UnixFileAttributeViews {
private static final String GID_NAME = "gid";
private static final String CTIME_NAME = "ctime";
+ // the names of the unix attributes (including posix)
+ static final Set unixAttributeNames =
+ Util.newSet(posixAttributeNames,
+ MODE_NAME, INO_NAME, DEV_NAME, RDEV_NAME,
+ NLINK_NAME, UID_NAME, GID_NAME, CTIME_NAME);
+
Unix(UnixPath file, boolean followLinks) {
super(file, followLinks);
}
@@ -316,13 +327,13 @@ class UnixFileAttributeViews {
}
@Override
- public Map readAttributes(String[] attributes)
+ public Map readAttributes(String[] requested)
throws IOException
{
- AttributesBuilder builder = AttributesBuilder.create(attributes);
+ AttributesBuilder builder =
+ AttributesBuilder.create(unixAttributeNames, requested);
UnixFileAttributes attrs = readAttributes();
- addBasicAttributesToBuilder(attrs, builder);
- addPosixAttributesToBuilder(attrs, builder);
+ addRequestedPosixAttributes(attrs, builder);
if (builder.match(MODE_NAME))
builder.add(MODE_NAME, attrs.mode());
if (builder.match(INO_NAME))
diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
index 9ec49b8d37a..b392b56b7e9 100644
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
@@ -606,7 +606,9 @@ class UnixPath
@Override
public boolean startsWith(Path other) {
- UnixPath that = toUnixPath(other);
+ if (!(Objects.requireNonNull(other) instanceof UnixPath))
+ return false;
+ UnixPath that = (UnixPath)other;
// other path is longer
if (that.path.length > path.length)
@@ -655,7 +657,9 @@ class UnixPath
@Override
public boolean endsWith(Path other) {
- UnixPath that = toUnixPath(other);
+ if (!(Objects.requireNonNull(other) instanceof UnixPath))
+ return false;
+ UnixPath that = (UnixPath)other;
int thisLen = path.length;
int thatLen = that.path.length;
diff --git a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c
index e6eaa0aa2f5..9a5b78e7723 100644
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c
@@ -60,7 +60,7 @@ Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[MAXHOSTNAMELEN+1];
hostname[0] = '\0';
- if (JVM_GetHostName(hostname, MAXHOSTNAMELEN)) {
+ if (JVM_GetHostName(hostname, sizeof(hostname))) {
/* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost");
} else {
@@ -83,6 +83,9 @@ Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
int h_error=0;
+ // ensure null-terminated
+ hostname[MAXHOSTNAMELEN] = '\0';
+
#ifdef __GLIBC__
gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
#else
diff --git a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c
index 5db03bf36fa..835969d7761 100644
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c
@@ -64,10 +64,12 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[NI_MAXHOST+1];
hostname[0] = '\0';
- if (JVM_GetHostName(hostname, MAXHOSTNAMELEN)) {
+ if (JVM_GetHostName(hostname, sizeof(hostname))) {
/* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost");
} else {
+ // ensure null-terminated
+ hostname[NI_MAXHOST] = '\0';
#ifdef __linux__
/* On Linux gethostname() says "host.domain.sun.com". On
* Solaris gethostname() says "host", so extra work is needed.
diff --git a/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c b/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c
index 0c1275b3bc2..f84c08edf66 100644
--- a/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c
+++ b/jdk/src/solaris/native/sun/awt/awt_DrawingSurface.c
@@ -302,6 +302,7 @@ awt_DrawingSurface_FreeDrawingSurfaceInfo(JAWT_DrawingSurfaceInfo* dsi)
#ifdef DEBUG
fprintf(stderr, "Drawing Surface Info is NULL\n");
#endif
+ return;
}
free(dsi->platformInfo);
free(dsi);
diff --git a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
index 45184950931..b548df4bf5d 100644
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
@@ -240,7 +240,7 @@ makeDefaultConfig(JNIEnv *env, int screen) {
AwtGraphicsConfigDataPtr defaultConfig;
int xinawareScreen = 0;
- VisualID forcedVisualID, defaultVisualID;
+ VisualID forcedVisualID = 0, defaultVisualID;
char *forcedVisualStr;
XVisualInfo vinfo;
long mask;
@@ -254,7 +254,7 @@ makeDefaultConfig(JNIEnv *env, int screen) {
if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {
mask = VisualIDMask | VisualScreenMask;
- if (sscanf(forcedVisualStr, "%x", &forcedVisualID) > 0 &&
+ if (sscanf(forcedVisualStr, "%lx", &forcedVisualID) > 0 &&
forcedVisualID > 0)
{
vinfo.visualid = forcedVisualID;
diff --git a/jdk/src/solaris/native/sun/nio/ch/Net.c b/jdk/src/solaris/native/sun/nio/ch/Net.c
index c43664c5000..9f9b4669a8e 100644
--- a/jdk/src/solaris/native/sun/nio/ch/Net.c
+++ b/jdk/src/solaris/native/sun/nio/ch/Net.c
@@ -154,6 +154,22 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
}
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
+{
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
+{
+#ifdef __solaris__
+ return JNI_TRUE;
+#else
+ return JNI_FALSE;
+#endif
+}
+
JNIEXPORT int JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse)
diff --git a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
index 65969a877d5..5590523b6ae 100644
--- a/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
+++ b/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
@@ -26,6 +26,7 @@ package java.net;
import java.io.IOException;
import java.io.FileDescriptor;
+import sun.net.ResourceManager;
/**
* This class defines the plain DatagramSocketImpl that is used for all
@@ -108,6 +109,7 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
protected void close() {
if (fd != null || fd1 != null) {
datagramSocketClose();
+ ResourceManager.afterUdpClose();
fd = null;
fd1 = null;
}
diff --git a/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index c9c26517d9b..c4b20db6495 100644
--- a/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/jdk/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -45,6 +45,9 @@ public class NTLMAuthentication extends AuthenticationInfo {
private static final long serialVersionUID = 100L;
+ private static final NTLMAuthenticationCallback NTLMAuthCallback =
+ NTLMAuthenticationCallback.getNTLMAuthenticationCallback();
+
private String hostname;
private static String defaultDomain; /* Domain to use if not specified by user */
@@ -142,6 +145,14 @@ public class NTLMAuthentication extends AuthenticationInfo {
return true;
}
+ /**
+ * Returns true if the given site is trusted, i.e. we can try
+ * transparent Authentication.
+ */
+ public static boolean isTrustedSite(URL url) {
+ return NTLMAuthCallback.isTrustedSite(url);
+ }
+
/**
* Not supported. Must use the setHeaders() method
*/
diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
index 8a81b87a0ab..67e5be670e0 100644
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java
@@ -157,6 +157,11 @@ class WindowsFileAttributeViews {
private static final String HIDDEN_NAME = "hidden";
private static final String ATTRIBUTES_NAME = "attributes";
+ // the names of the DOS attribtues (includes basic)
+ static final Set dosAttributeNames =
+ Util.newSet(basicAttributeNames,
+ READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME, ATTRIBUTES_NAME);
+
Dos(WindowsPath file, boolean followLinks) {
super(file, followLinks);
}
@@ -193,9 +198,10 @@ class WindowsFileAttributeViews {
public Map readAttributes(String[] attributes)
throws IOException
{
- AttributesBuilder builder = AttributesBuilder.create(attributes);
+ AttributesBuilder builder =
+ AttributesBuilder.create(dosAttributeNames, attributes);
WindowsFileAttributes attrs = readAttributes();
- addBasicAttributesToBuilder(attrs, builder);
+ addRequestedBasicAttributes(attrs, builder);
if (builder.match(READONLY_NAME))
builder.add(READONLY_NAME, attrs.isReadOnly());
if (builder.match(ARCHIVE_NAME))
diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
index 26c2b26ce8e..eb35de8167e 100644
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
@@ -646,7 +646,9 @@ class WindowsPath extends AbstractPath {
@Override
public boolean startsWith(Path obj) {
- WindowsPath other = toWindowsPath(obj);
+ if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
+ return false;
+ WindowsPath other = (WindowsPath)obj;
// if this path has a root component the given path's root must match
if (!this.root.equalsIgnoreCase(other.root)) {
@@ -675,7 +677,9 @@ class WindowsPath extends AbstractPath {
@Override
public boolean endsWith(Path obj) {
- WindowsPath other = toWindowsPath(obj);
+ if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
+ return false;
+ WindowsPath other = (WindowsPath)obj;
// other path is longer
if (other.path.length() > this.path.length()) {
diff --git a/jdk/src/windows/native/sun/nio/ch/Net.c b/jdk/src/windows/native/sun/nio/ch/Net.c
index b415cdfc3e2..75c9ba4ce66 100644
--- a/jdk/src/windows/native/sun/nio/ch/Net.c
+++ b/jdk/src/windows/native/sun/nio/ch/Net.c
@@ -100,6 +100,18 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
return JNI_FALSE;
}
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
+{
+ return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
+{
+ return JNI_FALSE;
+}
+
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse)
diff --git a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
index 7533cc12811..91ed2cb84bb 100644
--- a/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
+++ b/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -1032,12 +1032,12 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
// XXX Cannot use %02.2ld, because the leading 0 is ignored for integers.
// So, print them to strings, and then print them to the master string with a
// format pattern that makes it two digits and prefix with a 0 if necessary.
- swprintf( (wchar_t *)month, L"%2.2d", systemTime.wMonth);
- swprintf( (wchar_t *)day, L"%2.2d", systemTime.wDay);
- swprintf( (wchar_t *)hour, L"%2.2d", systemTime.wHour);
- swprintf( (wchar_t *)minute, L"%2.2d", systemTime.wMinute);
- swprintf( (wchar_t *)second, L"%2.2d", systemTime.wSecond);
- swprintf( (wchar_t *)timeString,
+ swprintf( (wchar_t *)month, 3, L"%2.2d", systemTime.wMonth);
+ swprintf( (wchar_t *)day, 3, L"%2.2d", systemTime.wDay);
+ swprintf( (wchar_t *)hour, 3, L"%2.2d", systemTime.wHour);
+ swprintf( (wchar_t *)minute, 3, L"%2.2d", systemTime.wMinute);
+ swprintf( (wchar_t *)second, 3, L"%2.2d", systemTime.wSecond);
+ swprintf( (wchar_t *)timeString, 16,
L"%ld%02.2s%02.2s%02.2s%02.2s%02.2sZ",
systemTime.wYear,
month,
diff --git a/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c b/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c
index 07b136aba2d..6086ddf30f0 100644
--- a/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c
+++ b/jdk/src/windows/native/sun/tools/attach/WindowsVirtualMachine.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -173,24 +173,45 @@ JNIEXPORT jbyteArray JNICALL Java_sun_tools_attach_WindowsVirtualMachine_generat
JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_openProcess
(JNIEnv *env, jclass cls, jint pid)
{
- HANDLE hProcess;
+ HANDLE hProcess = NULL;
- /*
- * Attempt to open process. If it fails then we try to enable the
- * SE_DEBUG_NAME privilege and retry.
- */
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
- if (hProcess == NULL && GetLastError() == ERROR_ACCESS_DENIED) {
- hProcess = doPrivilegedOpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
+ if (pid == (jint) GetCurrentProcessId()) {
+ /* process is attaching to itself; get a pseudo handle instead */
+ hProcess = GetCurrentProcess();
+ /* duplicate the pseudo handle so it can be used in more contexts */
+ if (DuplicateHandle(hProcess, hProcess, hProcess, &hProcess,
+ PROCESS_ALL_ACCESS, FALSE, 0) == 0) {
+ /*
+ * Could not duplicate the handle which isn't a good sign,
+ * but we'll try again with OpenProcess() below.
+ */
+ hProcess = NULL;
+ }
}
if (hProcess == NULL) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- JNU_ThrowIOException(env, "no such process");
- } else {
- JNU_ThrowIOExceptionWithLastError(env, "OpenProcess failed");
+ /*
+ * Attempt to open process. If it fails then we try to enable the
+ * SE_DEBUG_NAME privilege and retry.
+ */
+ hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
+ if (hProcess == NULL && GetLastError() == ERROR_ACCESS_DENIED) {
+ hProcess = doPrivilegedOpenProcess(PROCESS_ALL_ACCESS, FALSE,
+ (DWORD)pid);
+ }
+
+ if (hProcess == NULL) {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ JNU_ThrowIOException(env, "no such process");
+ } else {
+ char err_mesg[255];
+ /* include the last error in the default detail message */
+ sprintf(err_mesg, "OpenProcess(pid=%d) failed; LastError=0x%x",
+ (int)pid, (int)GetLastError());
+ JNU_ThrowIOExceptionWithLastError(env, err_mesg);
+ }
+ return (jlong)0;
}
- return (jlong)0;
}
/*
diff --git a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
index df0f263ddfc..1deff60252a 100644
--- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp
@@ -3699,7 +3699,9 @@ static void matchPaperSize(HDC printDC, HGLOBAL hDevMode, HGLOBAL hDevNames,
double* newWid, double *newHgt,
WORD* paperSize) {
- const double epsilon = 0.50;
+ // Tolerated differences in comparing page dimensions between passed in
+ // "orig" media with that of Windows' device.
+ const double epsilon = 3.6; // (1/72) of an inch
const double tolerance = (1.0 * 72.0); // # inches * 72
*newWid = origWid;
diff --git a/jdk/test/Makefile b/jdk/test/Makefile
index d26d19c544a..d1171b96027 100644
--- a/jdk/test/Makefile
+++ b/jdk/test/Makefile
@@ -399,12 +399,12 @@ $(foreach i,$1,$(wildcard ${i})) $(foreach i,$1,$(wildcard closed/${i}))
endef
# Running batches of tests with or without samevm
define RunSamevmBatch
-$(ECHO) "Running tests in samevm mode: $(call TestDirs, $?)"
-$(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=true UNIQUE_DIR=$@ jtreg_tests
+$(ECHO) "Running tests in samevm mode: $?"
+$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=true UNIQUE_DIR=$@ jtreg_tests
endef
define RunOthervmBatch
-$(ECHO) "Running tests in othervm mode: $(call TestDirs, $?)"
-$(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
+$(ECHO) "Running tests in othervm mode: $?"
+$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
endef
define SummaryInfo
$(ECHO) "########################################################"
@@ -420,27 +420,29 @@ JDK_ALL_TARGETS =
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has problems, and doesn't help performance as much as others.
JDK_ALL_TARGETS += jdk_awt
-jdk_awt: com/sun/awt java/awt sun/awt
+jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt)
$(call RunOthervmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_beans1
-jdk_beans1: java/beans/beancontext java/beans/PropertyChangeSupport \
+jdk_beans1: $(call TestDirs, \
+ java/beans/beancontext java/beans/PropertyChangeSupport \
java/beans/Introspector java/beans/Performance \
- java/beans/VetoableChangeSupport java/beans/Statement
+ java/beans/VetoableChangeSupport java/beans/Statement)
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_beans2
-jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
- java/beans/PropertyEditor
+jdk_beans2: $(call TestDirs, \
+ java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
+ java/beans/PropertyEditor)
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_beans3
-jdk_beans3: java/beans/XMLEncoder
+jdk_beans3: $(call TestDirs, java/beans/XMLEncoder)
$(call RunOthervmBatch)
# All beans tests
@@ -449,24 +451,24 @@ jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_io
-jdk_io: java/io
+jdk_io: $(call TestDirs, java/io)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_lang
-jdk_lang: java/lang
+jdk_lang: $(call TestDirs, java/lang)
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_management1
-jdk_management1: javax/management
+jdk_management1: $(call TestDirs, javax/management)
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_management2
-jdk_management2: com/sun/jmx com/sun/management sun/management
+jdk_management2: $(call TestDirs, com/sun/jmx com/sun/management sun/management)
$(call RunOthervmBatch)
# All management tests
@@ -475,36 +477,37 @@ jdk_management: jdk_management1 jdk_management2
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_math
-jdk_math: java/math
+jdk_math: $(call TestDirs, java/math)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_misc
-jdk_misc: demo javax/imageio javax/naming javax/print javax/script \
+jdk_misc: $(call TestDirs, \
+ demo javax/imageio javax/naming javax/print javax/script \
javax/smartcardio javax/sound com/sun/java com/sun/jndi \
- com/sun/org sun/misc sun/pisces
+ com/sun/org com/sun/xml sun/misc sun/pisces)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_net
-jdk_net: com/sun/net java/net sun/net
+jdk_net: $(call TestDirs, com/sun/net java/net sun/net)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_nio1
-jdk_nio1: java/nio/file
+jdk_nio1: $(call TestDirs, java/nio/file)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_nio2
-jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
- java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
+jdk_nio2: $(call TestDirs, java/nio/Buffer java/nio/ByteOrder \
+ java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer)
$(call SharedLibraryPermissions,java/nio/channels)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_nio3
-jdk_nio3: com/sun/nio sun/nio
+jdk_nio3: $(call TestDirs, com/sun/nio sun/nio)
$(call RunSamevmBatch)
# All nio tests
@@ -514,24 +517,25 @@ jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_rmi
-jdk_rmi: java/rmi javax/rmi sun/rmi
+jdk_rmi: $(call TestDirs, java/rmi javax/rmi sun/rmi)
$(call RunOthervmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_security1
-jdk_security1: java/security
+jdk_security1: $(call TestDirs, java/security)
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_security2
-jdk_security2: javax/crypto com/sun/crypto
+jdk_security2: $(call TestDirs, javax/crypto com/sun/crypto)
$(call RunOthervmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_security3
-jdk_security3: com/sun/security lib/security javax/security sun/security
+jdk_security3: $(call TestDirs, com/sun/security lib/security \
+ javax/security sun/security)
$(call SharedLibraryPermissions,sun/security)
$(call RunOthervmBatch)
@@ -542,23 +546,25 @@ jdk_security: jdk_security1 jdk_security2 jdk_security3
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has problems, and doesn't help performance as much as others.
JDK_ALL_TARGETS += jdk_swing
-jdk_swing: javax/swing sun/java2d
+jdk_swing: $(call TestDirs, javax/swing sun/java2d)
$(call RunOthervmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_text
-jdk_text: java/text sun/text
+jdk_text: $(call TestDirs, java/text sun/text)
$(call RunSamevmBatch)
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_tools1
-jdk_tools1: com/sun/jdi
+jdk_tools1: $(call TestDirs, com/sun/jdi)
$(call RunSamevmBatch)
# Stable othervm testruns (minus items from PROBLEM_LIST)
# Using samevm has serious problems with these tests
JDK_ALL_TARGETS += jdk_tools2
-jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
+jdk_tools2: $(call TestDirs, \
+ com/sun/tools sun/jvmstat sun/tools tools vm \
+ com/sun/servicetag com/sun/tracing)
$(call SharedLibraryPermissions,tools/launcher)
$(call RunSamevmBatch)
@@ -568,7 +574,7 @@ jdk_tools: jdk_tools1 jdk_tools2
# Stable samevm testruns (minus items from PROBLEM_LIST)
JDK_ALL_TARGETS += jdk_util
-jdk_util: java/util sun/util
+jdk_util: $(call TestDirs, java/util sun/util)
$(call RunSamevmBatch)
# ------------------------------------------------------------------
diff --git a/jdk/test/java/awt/font/TextLayout/CombiningPerf.java b/jdk/test/java/awt/font/TextLayout/CombiningPerf.java
new file mode 100644
index 00000000000..d51e586e507
--- /dev/null
+++ b/jdk/test/java/awt/font/TextLayout/CombiningPerf.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/**
+ * @test
+ * @bug 6328154 6962082
+ * @summary ensure that ascii, and latin-1 text without combining marks, both layout faster
+ * than latin-1 text with combining marks. The presumption is then that the canonical
+ * GSUB table is being run only on the latter and not on either of the former.
+ */
+
+import java.awt.Font;
+import java.awt.GraphicsEnvironment;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextLayout;
+
+import static java.awt.Font.*;
+
+public class CombiningPerf {
+ private static Font font;
+ private static FontRenderContext frc;
+
+ public static void main(String[] args) throws Exception {
+ System.err.println("start");
+
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+
+ font = new Font("Lucida Sans Regular", PLAIN, 12);
+ frc = new FontRenderContext(null, false, false);
+
+ String ascii = "the characters are critical noodles?";
+ String french = "l'aper\u00e7u caract\u00e8re one \u00e9t\u00e9 cr\u00e9\u00e9s";
+ String frenchX = "l'aper\u00e7u caracte\u0300re one e\u0301te\u0301 ere\u0301e\u0301s";
+
+ // warmup
+ for (int i = 0; i < 100; ++i) {
+ TextLayout tl = new TextLayout(french, font, frc);
+ tl = new TextLayout(ascii, font, frc);
+ tl = new TextLayout(frenchX, font, frc);
+ }
+ /**/
+ long atime = test(ascii);
+ System.err.println("atime: " + (atime/1000000.0) + " length: " + ascii.length());
+
+ long ftime = test(french);
+ System.err.println("ftime: " + (ftime/1000000.0) + " length: " + french.length());
+
+ long xtime = test(frenchX);
+ System.err.println("xtime: " + (xtime/1000000.0) + " length: " + frenchX.length());
+
+ long limit = xtime * 2 / 3;
+ if (atime > limit || ftime > limit) {
+ throw new Exception("took too long");
+ }
+ /**/
+ }
+
+ private static long test(String text) {
+ long start = System.nanoTime();
+ for (int i = 0; i < 2000; ++i) {
+ TextLayout tl = new TextLayout(text, font, frc);
+ }
+ return System.nanoTime() - start;
+ }
+}
diff --git a/jdk/test/java/awt/font/TextLayout/KernCrash.java b/jdk/test/java/awt/font/TextLayout/KernCrash.java
new file mode 100644
index 00000000000..50e44d4c30d
--- /dev/null
+++ b/jdk/test/java/awt/font/TextLayout/KernCrash.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011, 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.io.*;
+import java.awt.*;
+import java.awt.font.*;
+import java.util.*;
+
+/**
+ * Shows (top) with kerning, (middle) without, (bottom) also without.
+ *
+ * @bug 7017324
+ */
+public class KernCrash extends Frame {
+ private static Font font0;
+ private static Font font1;
+ private static Font font2;
+
+ public static void main(String[] args) throws Exception {
+ HashMap attrs = new HashMap();
+ font0 = Font.createFont(Font.TRUETYPE_FONT, new File("Vera.ttf"));
+ System.out.println("using " + font0);
+ attrs.put(TextAttribute.SIZE, new Float(58f));
+ font1 = font0.deriveFont(attrs);
+ attrs.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
+ font2 = font0.deriveFont(attrs);
+
+ KernCrash f = new KernCrash();
+ f.setTitle("Kerning Crash");
+ f.setSize(600, 300);
+ f.setForeground(Color.black);
+ f.show();
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D)g;
+ FontRenderContext frc = g2.getFontRenderContext();
+ TextLayout layout = new TextLayout("text", font2, frc);
+ layout.draw(g2, 10, 150);
+
+ String s = "WAVATastic";
+ TextLayout layout2 = new TextLayout(s, font1, frc);
+ layout2.draw(g2, 10, 200);
+ TextLayout layout3 = new TextLayout(s, font2, frc);
+ layout3.draw(g2, 10, 100);
+ }
+}
diff --git a/jdk/test/java/lang/invoke/6987555/Test6987555.java b/jdk/test/java/lang/invoke/6987555/Test6987555.java
new file mode 100644
index 00000000000..465da236d7c
--- /dev/null
+++ b/jdk/test/java/lang/invoke/6987555/Test6987555.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2010, 2011, 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6987555
+ * @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
+ *
+ * @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
+ */
+
+import java.lang.invoke.*;
+
+public class Test6987555 {
+ private static final Class CLASS = Test6987555.class;
+ private static final String NAME = "foo";
+ private static final boolean DEBUG = false;
+
+ public static void main(String[] args) throws Throwable {
+ testboolean();
+ testbyte();
+ testchar();
+ testshort();
+ testint();
+ }
+
+ // boolean
+ static void testboolean() throws Throwable {
+ doboolean(false);
+ doboolean(true);
+ }
+ static void doboolean(boolean x) throws Throwable {
+ if (DEBUG) System.out.println("boolean=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(boolean.class, boolean.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(boolean.class, Boolean.class));
+ boolean a = (boolean) mh1.invokeExact(x);
+ boolean b = (boolean) mh2.invokeExact(Boolean.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // byte
+ static void testbyte() throws Throwable {
+ byte[] a = new byte[] {
+ Byte.MIN_VALUE,
+ Byte.MIN_VALUE + 1,
+ -0x0F,
+ -1,
+ 0,
+ 1,
+ 0x0F,
+ Byte.MAX_VALUE - 1,
+ Byte.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dobyte(a[i]);
+ }
+ }
+ static void dobyte(byte x) throws Throwable {
+ if (DEBUG) System.out.println("byte=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(byte.class, byte.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(byte.class, Byte.class));
+ byte a = (byte) mh1.invokeExact(x);
+ byte b = (byte) mh2.invokeExact(Byte.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // char
+ static void testchar() throws Throwable {
+ char[] a = new char[] {
+ Character.MIN_VALUE,
+ Character.MIN_VALUE + 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Character.MAX_VALUE - 1,
+ Character.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dochar(a[i]);
+ }
+ }
+ static void dochar(char x) throws Throwable {
+ if (DEBUG) System.out.println("char=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(char.class, char.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(char.class, Character.class));
+ char a = (char) mh1.invokeExact(x);
+ char b = (char) mh2.invokeExact(Character.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // short
+ static void testshort() throws Throwable {
+ short[] a = new short[] {
+ Short.MIN_VALUE,
+ Short.MIN_VALUE + 1,
+ -0x0FFF,
+ -0x00FF,
+ -0x000F,
+ -1,
+ 0,
+ 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Short.MAX_VALUE - 1,
+ Short.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doshort(a[i]);
+ }
+ }
+ static void doshort(short x) throws Throwable {
+ if (DEBUG) System.out.println("short=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(short.class, short.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(short.class, Short.class));
+ short a = (short) mh1.invokeExact(x);
+ short b = (short) mh2.invokeExact(Short.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // int
+ static void testint() throws Throwable {
+ int[] a = new int[] {
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ -0x00000FFF,
+ -0x000000FF,
+ -0x0000000F,
+ -1,
+ 0,
+ 1,
+ 0x0000000F,
+ 0x000000FF,
+ 0x00000FFF,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doint(a[i]);
+ }
+ }
+ static void doint(int x) throws Throwable {
+ if (DEBUG) System.out.println("int=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(int.class, int.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(int.class, Integer.class));
+ int a = (int) mh1.invokeExact(x);
+ int b = (int) mh2.invokeExact(Integer.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ public static boolean foo(boolean i) { return i; }
+ public static byte foo(byte i) { return i; }
+ public static char foo(char i) { return i; }
+ public static short foo(short i) { return i; }
+ public static int foo(int i) { return i; }
+}
diff --git a/jdk/test/java/lang/invoke/6991596/Test6991596.java b/jdk/test/java/lang/invoke/6991596/Test6991596.java
new file mode 100644
index 00000000000..e02bcfc819e
--- /dev/null
+++ b/jdk/test/java/lang/invoke/6991596/Test6991596.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2010, 2011, 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6991596
+ * @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
+ *
+ * @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
+ */
+
+import java.lang.invoke.*;
+
+public class Test6991596 {
+ private static final Class CLASS = Test6991596.class;
+ private static final String NAME = "foo";
+ private static final boolean DEBUG = System.getProperty("DEBUG", "false").equals("true");
+
+ public static void main(String[] args) throws Throwable {
+ testboolean();
+ testbyte();
+ testchar();
+ testshort();
+ testint();
+ testlong();
+ }
+
+ // Helpers to get various methods.
+ static MethodHandle getmh1(Class ret, Class arg) throws ReflectiveOperationException {
+ return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
+ }
+ static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
+ return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+ }
+ static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
+ return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+ }
+
+ // test adapter_opt_i2i
+ static void testboolean() throws Throwable {
+ boolean[] a = new boolean[] {
+ true,
+ false
+ };
+ for (int i = 0; i < a.length; i++) {
+ doboolean(a[i]);
+ }
+ }
+ static void doboolean(boolean x) throws Throwable {
+ if (DEBUG) System.out.println("boolean=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
+ // TODO add this for all cases when the bugs are fixed.
+ //MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
+ boolean a = (boolean) mh1.invokeExact((boolean) x);
+ boolean b = (boolean) mh2.invokeExact(x);
+ //boolean c = mh3.invokeExact((boolean) x);
+ check(x, a, b);
+ //check(x, c, x);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class );
+ MethodHandle mh2 = getmh2(mh1, byte.class, boolean.class);
+ byte a = (byte) mh1.invokeExact((byte) (x ? 1 : 0));
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
+ char a = (char) mh1.invokeExact((char) (x ? 1 : 0));
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
+ short a = (short) mh1.invokeExact((short) (x ? 1 : 0));
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testbyte() throws Throwable {
+ byte[] a = new byte[] {
+ Byte.MIN_VALUE,
+ Byte.MIN_VALUE + 1,
+ -0x0F,
+ -1,
+ 0,
+ 1,
+ 0x0F,
+ Byte.MAX_VALUE - 1,
+ Byte.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dobyte(a[i]);
+ }
+ }
+ static void dobyte(byte x) throws Throwable {
+ if (DEBUG) System.out.println("byte=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testchar() throws Throwable {
+ char[] a = new char[] {
+ Character.MIN_VALUE,
+ Character.MIN_VALUE + 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Character.MAX_VALUE - 1,
+ Character.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dochar(a[i]);
+ }
+ }
+ static void dochar(char x) throws Throwable {
+ if (DEBUG) System.out.println("char=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, char.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, char.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testshort() throws Throwable {
+ short[] a = new short[] {
+ Short.MIN_VALUE,
+ Short.MIN_VALUE + 1,
+ -0x0FFF,
+ -0x00FF,
+ -0x000F,
+ -1,
+ 0,
+ 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Short.MAX_VALUE - 1,
+ Short.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doshort(a[i]);
+ }
+ }
+ static void doshort(short x) throws Throwable {
+ if (DEBUG) System.out.println("short=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, short.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, short.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testint() throws Throwable {
+ int[] a = new int[] {
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ -0x0FFFFFFF,
+ -0x00FFFFFF,
+ -0x000FFFFF,
+ -0x0000FFFF,
+ -0x00000FFF,
+ -0x000000FF,
+ -0x0000000F,
+ -1,
+ 0,
+ 1,
+ 0x0000000F,
+ 0x000000FF,
+ 0x00000FFF,
+ 0x0000FFFF,
+ 0x000FFFFF,
+ 0x00FFFFFF,
+ 0x0FFFFFFF,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doint(a[i]);
+ }
+ }
+ static void doint(int x) throws Throwable {
+ if (DEBUG) System.out.println("int=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, int.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, int.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ assert a == b : a + " != " + b;
+ check(x, a, b);
+ }
+
+ // int
+ {
+ MethodHandle mh1 = getmh1( int.class, int.class);
+ MethodHandle mh2 = getmh2(mh1, int.class, int.class);
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ // test adapter_opt_l2i
+ static void testlong() throws Throwable {
+ long[] a = new long[] {
+ Long.MIN_VALUE,
+ Long.MIN_VALUE + 1,
+ -0x000000000FFFFFFFL,
+ -0x0000000000FFFFFFL,
+ -0x00000000000FFFFFL,
+ -0x000000000000FFFFL,
+ -0x0000000000000FFFL,
+ -0x00000000000000FFL,
+ -0x000000000000000FL,
+ -1L,
+ 0L,
+ 1L,
+ 0x000000000000000FL,
+ 0x00000000000000FFL,
+ 0x0000000000000FFFL,
+ 0x0000000000000FFFL,
+ 0x000000000000FFFFL,
+ 0x00000000000FFFFFL,
+ 0x0000000000FFFFFFL,
+ 0x000000000FFFFFFFL,
+ Long.MAX_VALUE - 1,
+ Long.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dolong(a[i]);
+ }
+ }
+ static void dolong(long x) throws Throwable {
+ if (DEBUG) System.out.println("long=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1L) == 1L);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, long.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, long.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // int
+ {
+ MethodHandle mh1 = getmh1( int.class, int.class);
+ MethodHandle mh2 = getmh2(mh1, int.class, long.class);
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void check(boolean x, boolean e, boolean a) { p(z2h(x), z2h(e), z2h(a)); assert e == a : z2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(boolean x, byte e, byte a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(boolean x, int e, int a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(int x, boolean e, boolean a) { p(i2h(x), z2h(e), z2h(a)); assert e == a : i2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(int x, byte e, byte a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(int x, int e, int a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(long x, boolean e, boolean a) { p(l2h(x), z2h(e), z2h(a)); assert e == a : l2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(long x, byte e, byte a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(long x, int e, int a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void p(String x, String e, String a) { if (DEBUG) System.out.println(x + ": expected: " + e + ", actual: " + a); }
+
+ static String z2h(boolean x) { return x ? "1" : "0"; }
+ static String i2h(int x) { return Integer.toHexString(x); }
+ static String l2h(long x) { return Long.toHexString(x); }
+
+ // to int
+ public static boolean foo(boolean i) { return i; }
+ public static byte foo(byte i) { return i; }
+ public static char foo(char i) { return i; }
+ public static short foo(short i) { return i; }
+ public static int foo(int i) { return i; }
+}
diff --git a/jdk/test/java/dyn/ClassValueTest.java b/jdk/test/java/lang/invoke/ClassValueTest.java
similarity index 94%
rename from jdk/test/java/dyn/ClassValueTest.java
rename to jdk/test/java/lang/invoke/ClassValueTest.java
index f917e9581da..59c5a658c7e 100644
--- a/jdk/test/java/dyn/ClassValueTest.java
+++ b/jdk/test/java/lang/invoke/ClassValueTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -26,21 +26,21 @@
/* @test
* @summary tests for class-specific values
* @compile ClassValueTest.java
- * @run junit/othervm test.java.dyn.ClassValueTest
+ * @run junit/othervm test.java.lang.invoke.ClassValueTest
*/
/*
Manually:
- $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/dyn/ClassValueTest.java
- $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.dyn.ClassValueTest
+ $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/lang/invoke/ClassValueTest.java
+ $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.lang.invoke.ClassValueTest
Output: .testAdd => 1000 : Integer
*/
-package test.java.dyn;
+package test.java.lang.invoke;
import java.util.*;
-import java.dyn.*;
+import java.lang.invoke.*;
import org.junit.*;
import static org.junit.Assert.*;
diff --git a/jdk/test/java/dyn/InvokeDynamicPrintArgs.java b/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java
similarity index 89%
rename from jdk/test/java/dyn/InvokeDynamicPrintArgs.java
rename to jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java
index 233c4fc316c..7089e959223 100644
--- a/jdk/test/java/dyn/InvokeDynamicPrintArgs.java
+++ b/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -29,19 +29,19 @@
* indify.Indify
* --verify-specifier-count=3 --transitionalJSR292=false
* --expand-properties --classpath ${test.classes}
- * --java test.java.dyn.InvokeDynamicPrintArgs --check-output
+ * --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
*/
-package test.java.dyn;
+package test.java.lang.invoke;
import org.junit.Test;
import java.util.*;
import java.io.*;
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
public class InvokeDynamicPrintArgs {
public static void main(String... av) throws Throwable {
@@ -65,7 +65,7 @@ public class InvokeDynamicPrintArgs {
String[] args = new String[]{
"--verify-specifier-count=3", "--transitionalJSR292=false",
"--expand-properties", "--classpath", testClassPath,
- "--java", "test.java.dyn.InvokeDynamicPrintArgs", "--check-output"
+ "--java", "test.java.lang.invoke.InvokeDynamicPrintArgs", "--check-output"
};
System.err.println("Indify: "+Arrays.toString(args));
indify.Indify.main(args);
@@ -97,11 +97,11 @@ public class InvokeDynamicPrintArgs {
}
private static final String[] EXPECT_OUTPUT = {
"Printing some argument lists, starting with a empty one:",
- "[test.java.dyn.InvokeDynamicPrintArgs, nothing, ()void][]",
- "[test.java.dyn.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
- "[test.java.dyn.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
- "[test.java.dyn.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
- "[test.java.dyn.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, nothing, ()void][]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
"Done printing argument lists."
};
diff --git a/jdk/test/java/dyn/InvokeGenericTest.java b/jdk/test/java/lang/invoke/InvokeGenericTest.java
similarity index 97%
rename from jdk/test/java/dyn/InvokeGenericTest.java
rename to jdk/test/java/lang/invoke/InvokeGenericTest.java
index bae888060a0..f1aaf9eaa71 100644
--- a/jdk/test/java/dyn/InvokeGenericTest.java
+++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, 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
@@ -24,16 +24,16 @@
*/
/* @test
- * @summary unit tests for java.dyn.MethodHandle.invokeGeneric
+ * @summary unit tests for java.lang.invoke.MethodHandle.invokeGeneric
* @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.InvokeGenericTest
*/
-package test.java.dyn;
+package test.java.lang.invoke;
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
import java.lang.reflect.*;
import java.util.*;
import org.junit.*;
@@ -49,7 +49,7 @@ public class InvokeGenericTest {
// How much output?
static int verbosity = 0;
static {
- String vstr = System.getProperty("test.java.dyn.InvokeGenericTest.verbosity");
+ String vstr = System.getProperty("test.java.lang.invoke.InvokeGenericTest.verbosity");
if (vstr != null) verbosity = Integer.parseInt(vstr);
}
@@ -216,7 +216,7 @@ public class InvokeGenericTest {
if (wrap != null) {
return wrap;
}
-// import sun.dyn.util.Wrapper;
+// import sun.invoke.util.Wrapper;
// Wrapper wrap = Wrapper.forBasicType(dst);
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// wrap = Wrapper.forWrapperType(dst);
diff --git a/jdk/test/java/dyn/JavaDocExamplesTest.java b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java
similarity index 88%
rename from jdk/test/java/dyn/JavaDocExamplesTest.java
rename to jdk/test/java/lang/invoke/JavaDocExamplesTest.java
index 72a62851f82..7093ea2005a 100644
--- a/jdk/test/java/dyn/JavaDocExamplesTest.java
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java
@@ -24,27 +24,27 @@
*/
/* @test
- * @summary example code used in javadoc for java.dyn API
+ * @summary example code used in javadoc for java.lang.invoke API
* @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamplesTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.JavaDocExamplesTest
*/
/*
---- To run outside jtreg:
$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
- $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamplesTest.java
+ $DAVINCI/sources/jdk/test/java/lang/invoke/JavaDocExamplesTest.java
$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
-XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
- -Dtest.java.dyn.JavaDocExamplesTest.verbosity=1 \
- test.java.dyn.JavaDocExamplesTest
+ -Dtest.java.lang.invoke.JavaDocExamplesTest.verbosity=1 \
+ test.java.lang.invoke.JavaDocExamplesTest
----
*/
-package test.java.dyn;
+package test.java.lang.invoke;
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
import java.lang.reflect.*;
import java.util.*;
@@ -65,7 +65,7 @@ public class JavaDocExamplesTest {
org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
}
// How much output?
- static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamplesTest.verbosity", 0);
+ static int verbosity = Integer.getInteger("test.java.lang.invoke.JavaDocExamplesTest.verbosity", 0);
{}
static final private Lookup LOOKUP = lookup();
@@ -108,6 +108,16 @@ assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+ }}
+ {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d1 = dropArguments(cat, 1, String.class);
diff --git a/jdk/test/java/dyn/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java
similarity index 99%
rename from jdk/test/java/dyn/MethodHandlesTest.java
rename to jdk/test/java/lang/invoke/MethodHandlesTest.java
index b44f262fa02..bae38f766bc 100644
--- a/jdk/test/java/dyn/MethodHandlesTest.java
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java
@@ -24,15 +24,15 @@
*/
/* @test
- * @summary unit tests for java.dyn.MethodHandles
+ * @summary unit tests for java.lang.invoke.MethodHandles
* @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodHandlesTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodHandlesTest
*/
-package test.java.dyn;
+package test.java.lang.invoke;
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
+import java.lang.invoke.*;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.*;
import java.util.*;
import org.junit.*;
@@ -48,7 +48,7 @@ public class MethodHandlesTest {
// How much output?
static int verbosity = 0;
static {
- String vstr = System.getProperty("test.java.dyn.MethodHandlesTest.verbosity");
+ String vstr = System.getProperty("test.java.lang.invoke.MethodHandlesTest.verbosity");
if (vstr != null) verbosity = Integer.parseInt(vstr);
}
@@ -258,7 +258,7 @@ public class MethodHandlesTest {
if (wrap != null) {
return wrap;
}
-// import sun.dyn.util.Wrapper;
+// import sun.invoke.util.Wrapper;
// Wrapper wrap = Wrapper.forBasicType(dst);
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// wrap = Wrapper.forWrapperType(dst);
@@ -2264,7 +2264,7 @@ public class MethodHandlesTest {
}
}
}
-// Local abbreviated copy of sun.dyn.util.ValueConversions
+// Local abbreviated copy of sun.invoke.util.ValueConversions
class ValueConversions {
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
private static final Object[] NO_ARGS_ARRAY = {};
diff --git a/jdk/test/java/dyn/MethodTypeTest.java b/jdk/test/java/lang/invoke/MethodTypeTest.java
similarity index 82%
rename from jdk/test/java/dyn/MethodTypeTest.java
rename to jdk/test/java/lang/invoke/MethodTypeTest.java
index caadaa04a33..5cc32771624 100644
--- a/jdk/test/java/dyn/MethodTypeTest.java
+++ b/jdk/test/java/lang/invoke/MethodTypeTest.java
@@ -24,15 +24,14 @@
*/
/* @test
- * @summary unit tests for java.dyn.MethodType
+ * @summary unit tests for java.lang.invoke.MethodType
* @compile MethodTypeTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodTypeTest
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodTypeTest
*/
-package test.java.dyn;
+package test.java.lang.invoke;
-import sun.dyn.MemberName;
-import java.dyn.MethodType;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.*;
@@ -163,18 +162,6 @@ public class MethodTypeTest {
assertSame(expResult, result);
}
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_Method() {
- System.out.println("make (via MemberName.getMethodType)");
- MethodType expResult = MethodType.methodType(int.class, String.class);
- MemberName name = new MemberName(compareTo);
- MethodType result = name.getMethodType();
- assertSame(expResult, result);
- }
-
/**
* Test of make method, of class MethodType.
*/
@@ -476,10 +463,13 @@ public class MethodTypeTest {
@Test
public void testPortableSerialFormat() throws Throwable {
System.out.println("portable serial format");
+ boolean generateData = false;
+ //generateData = true; // set this true to generate the following input data:
Object[][] cases = {
{ mt_vv, new byte[] { // ()void
- (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
- (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
(byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
(byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
@@ -493,8 +483,9 @@ public class MethodTypeTest {
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
} },
{ mt_OO, new byte[] { // (Object)Object
- (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
- (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
(byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
(byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
@@ -509,14 +500,47 @@ public class MethodTypeTest {
(byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
(byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
} },
+ { mt_vOiSzA, new byte[] { // (Object,int,String,boolean,Object[])void
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+ (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+ (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+ (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+ (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+ (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+ (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00,
+ (byte)0x03, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+ (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76,
+ (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53,
+ (byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0xa0, (byte)0xf0, (byte)0xa4,
+ (byte)0x38, (byte)0x7a, (byte)0x3b, (byte)0xb3, (byte)0x42, (byte)0x02, (byte)0x00, (byte)0x00,
+ (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x07, (byte)0x62, (byte)0x6f,
+ (byte)0x6f, (byte)0x6c, (byte)0x65, (byte)0x61, (byte)0x6e, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x5b, (byte)0x4c,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+ (byte)0x3b, (byte)0x90, (byte)0xce, (byte)0x58, (byte)0x9f, (byte)0x10, (byte)0x73, (byte)0x29,
+ (byte)0x6c, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x78,
+ } },
};
- boolean generateData = false;
- //generateData = true;
for (Object[] c : cases) {
MethodType mt = (MethodType) c[0];
System.out.println("deserialize "+mt);
byte[] wire = (byte[]) c[1];
if (generateData) {
+ System.out.println("");
wire = writeSerial(mt);
final String INDENT = " ";
System.out.print("{ // "+mt);
@@ -528,6 +552,7 @@ public class MethodTypeTest {
}
System.out.println();
System.out.println(INDENT+"}");
+ System.out.println(" ");
System.out.flush();
}
Object decode;
diff --git a/jdk/test/java/dyn/indify/Indify.java b/jdk/test/java/lang/invoke/indify/Indify.java
similarity index 98%
rename from jdk/test/java/dyn/indify/Indify.java
rename to jdk/test/java/lang/invoke/indify/Indify.java
index ba24b79a9d9..ac0485a5ebc 100644
--- a/jdk/test/java/dyn/indify/Indify.java
+++ b/jdk/test/java/lang/invoke/indify/Indify.java
@@ -47,9 +47,9 @@ import java.util.regex.*;
* and {@code CONSTANT_MethodType} "ldc" instructions.
* The stereotyped code must create method types by calls to {@code methodType} or
* {@code fromMethodDescriptorString}. The "lookup" argument must be created
- * by calls to {@code java.dyn.MethodHandles#lookup MethodHandles.lookup}.
+ * by calls to {@code java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
* The class and string arguments must be constant.
- * The following methods of {@code java.dyn.MethodHandle.Lookup Lookup} are
+ * The following methods of {@code java.lang.invoke.MethodHandle.Lookup Lookup} are
* allowed for method handle creation: {@code findStatic}, {@code findVirtual},
* {@code findConstructor}, {@code findSpecial},
* {@code findGetter}, {@code findSetter},
@@ -350,10 +350,15 @@ public class Indify {
}
protected Class> findClass(String name) throws ClassNotFoundException {
try {
- return transformAndLoadClass(findClassInPath(name));
+ File f = findClassInPath(name);
+ if (f != null) {
+ Class> c = transformAndLoadClass(f);
+ if (c != null) return c;
+ }
} catch (IOException ex) {
throw new ClassNotFoundException("IO error", ex);
}
+ throw new ClassNotFoundException();
}
private Class> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
if (verbose) System.err.println("Loading class from "+f);
@@ -592,7 +597,9 @@ public class Indify {
if (s.startsWith("MT_")) return 'T';
else if (s.startsWith("MH_")) return 'H';
else if (s.startsWith("INDY_")) return 'I';
- else if (s.startsWith("java/dyn/")) return 'D';
+ else if (transitionalJSR292 &&
+ s.startsWith("java/dyn/")) return 'D';
+ else if (s.startsWith("java/lang/invoke/")) return 'D';
else if (s.startsWith("java/lang/")) return 'J';
return 0;
}
@@ -605,15 +612,24 @@ public class Indify {
String descr = cf.pool.getString(CONSTANT_Utf8, n2);
String requiredType;
switch (poolMarks[(char)n1]) {
- case 'H': requiredType = "()Ljava/dyn/MethodHandle;"; break;
- case 'T': requiredType = "()Ljava/dyn/MethodType;"; break;
- case 'I': requiredType = "()Ljava/dyn/MethodHandle;"; break;
+ case 'H': requiredType = "()Ljava/lang/invoke/MethodHandle;"; break;
+ case 'T': requiredType = "()Ljava/lang/invoke/MethodType;"; break;
+ case 'I': requiredType = "()Ljava/lang/invoke/MethodHandle;"; break;
default: return 0;
}
- if (descr.equals(requiredType)) return mark;
+ if (matchType(descr, requiredType)) return mark;
return 0;
}
+ boolean matchType(String descr, String requiredType) {
+ if (descr.equals(requiredType)) return true;
+ if (transitionalJSR292) {
+ String oldType = requiredType.replace("Ljava/lang/invoke/", "Ljava/dyn/");
+ if (descr.equals(oldType)) return true;
+ }
+ return false;
+ }
+
private class JVMState {
final List stack = new ArrayList<>();
int sp() { return stack.size(); }
diff --git a/jdk/test/java/net/URI/Test.java b/jdk/test/java/net/URI/Test.java
index f0bb8da821a..3f157ea7561 100644
--- a/jdk/test/java/net/URI/Test.java
+++ b/jdk/test/java/net/URI/Test.java
@@ -23,7 +23,7 @@
/* @test
* @summary Unit test for java.net.URI
- * @bug 4464135 4505046 4503239 4438319 4991359 4866303
+ * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363
* @author Mark Reinhold
*/
@@ -1050,6 +1050,13 @@ public class Test {
test("http://1.2.3.4.5").psa().x().z();
test("http://[1.2.3.4:5]").x().z();
test("http://1:2:3:4:5:6:7:8").psa().x().z();
+ test("http://[1.2.3.4]/").x().z();
+ test("http://[1.2.3.4/").x().z();
+ test("http://[foo]/").x().z();
+ test("http://[foo/").x().z();
+ test("s", "[foo]", "/", null, null).x().z();
+ test("s", "[foo", "/", null, null).x().z();
+ test("s", "[::foo", "/", null, null).x().z();
// Test hostnames that might initially look like IPv4 addresses
diff --git a/jdk/test/java/net/URLConnection/GetXmlContentType.java b/jdk/test/java/net/URLConnection/GetXmlContentType.java
index 5c3282d63ec..e89043a9781 100644
--- a/jdk/test/java/net/URLConnection/GetXmlContentType.java
+++ b/jdk/test/java/net/URLConnection/GetXmlContentType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -23,8 +23,8 @@
/*
* @test
- * @bug 4160195
- * @summary Check for correct detection of XML content type
+ * @bug 4160195 7026346
+ * @summary Check for correct detection of XML content type, including BOM streams
*/
import java.io.*;
@@ -34,6 +34,8 @@ import java.net.*;
public class GetXmlContentType {
static final String XML_MIME_TYPE = "application/xml";
+ static final String XML_HEADER = " 0)
+ throw new RuntimeException (
+ "Test failed; passed = " + passed + ", failed = " + failed);
+ }
+
+ static void contentTypeFromFile() throws Exception {
// POSITIVE tests: good data --> good result
- //
- for (int i = 0; i < goodFiles.length; i++) {
- String result = getUrlContentType (goodFiles [i]);
- if (!XML_MIME_TYPE.equals (result)) {
- System.out.println ("Wrong MIME type: "
- + goodFiles [i]
- + " --> " + result
- );
- sawError = true;
+ for (String goodFile : goodFiles) {
+ String result = getUrlContentType(goodFile);
+
+ if (!XML_MIME_TYPE.equals(result)) {
+ System.out.println("Wrong MIME type: " + goodFile + " --> " + result);
+ failed++;
+ } else {
+ passed++;
}
}
- //
// NEGATIVE tests: bad data --> correct diagnostic
- //
- for (int i = 0; i < badFiles.length; i++) {
- String result = getUrlContentType (badFiles [i]);
+ for (String badFile : badFiles) {
+ String result = getUrlContentType(badFile);
- if (XML_MIME_TYPE.equals (result)) {
- System.out.println ("Wrong MIME type: "
- + badFiles [i]
- + " --> " + result
- );
- sawError = true;
+ if (XML_MIME_TYPE.equals(result)) {
+ System.out.println("Wrong MIME type: " + badFile + " --> " + result);
+ failed++;
+ } else {
+ passed++;
}
}
-
- if (sawError)
- throw new Exception (
- "GetXmlContentType Test failed; see diagnostics.");
}
- static String getUrlContentType (String name) throws IOException {
- File file = new File(System.getProperty("test.src", "."), "xml");
- URL u = new URL ("file:"
- + file.getCanonicalPath()
- + file.separator
- + name);
- URLConnection conn = u.openConnection ();
+ static String getUrlContentType(String name) throws IOException {
+ File file = new File(System.getProperty("test.src", "."), "xml");
+ URL u = new URL("file:"
+ + file.getCanonicalPath()
+ + file.separator
+ + name);
+ URLConnection conn = u.openConnection();
- return conn.getContentType ();
+ return conn.getContentType();
}
+ static void contentTypeFromBOMStream() throws Exception {
+ final String[] encodings = new String[]
+ {"UTF-8", "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE"};
+ for (String encoding : encodings) {
+ try (InputStream is = new ByteArrayInputStream(toBOMBytes(encoding))) {
+ String mime = URLConnection.guessContentTypeFromStream(is);
+ if ( !XML_MIME_TYPE.equals(mime) ) {
+ System.out.println("Wrong MIME type: " + encoding + " --> " + mime);
+ failed++;
+ } else {
+ passed++;
+ }
+ }
+ }
+ }
+
+ static byte[] toBOMBytes(String encoding) throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ switch (encoding) {
+ case "UTF-8" :
+ bos.write(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF });
+ break;
+ case "UTF-16BE" :
+ bos.write(new byte[] { (byte) 0xFE, (byte) 0xFF });
+ break;
+ case "UTF-16LE" :
+ bos.write(new byte[] { (byte) 0xFF, (byte) 0xFE });
+ break;
+ case "UTF-32BE" :
+ bos.write(new byte[] { (byte) 0x00, (byte) 0x00,
+ (byte) 0xFE, (byte) 0xFF });
+ break;
+ case "UTF-32LE" :
+ bos.write(new byte[] { (byte) 0xFF, (byte) 0xFE,
+ (byte) 0x00, (byte) 0x00 });
+ }
+
+ bos.write(XML_HEADER.getBytes(encoding));
+ return bos.toByteArray();
+ }
}
diff --git a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java
index aa79e2214df..f4445bb946f 100644
--- a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java
+++ b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4527345
+ * @bug 4527345 7026376
* @summary Unit test for DatagramChannel's multicast support
* @build MulticastSendReceiveTests NetworkConfiguration
* @run main MulticastSendReceiveTests
@@ -31,12 +31,19 @@
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
+import static java.net.StandardProtocolFamily.*;
import java.util.*;
import java.io.IOException;
public class MulticastSendReceiveTests {
- static Random rand = new Random();
+ static final Random rand = new Random();
+
+ static final ProtocolFamily UNSPEC = new ProtocolFamily() {
+ public String name() {
+ return "UNSPEC";
+ }
+ };
/**
* Send datagram from given local address to given multicast
@@ -130,75 +137,84 @@ public class MulticastSendReceiveTests {
/**
* Exercise multicast send/receive on given group/interface
*/
- static void test(NetworkInterface nif, InetAddress group, InetAddress source)
+ static void test(ProtocolFamily family,
+ NetworkInterface nif,
+ InetAddress group,
+ InetAddress source)
throws IOException
{
- ProtocolFamily family = (group instanceof Inet6Address) ?
- StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
- System.out.format("create channel to %s socket\n", family.name());
- DatagramChannel dc = DatagramChannel.open(family)
- .setOption(StandardSocketOption.SO_REUSEADDR, true)
- .bind(new InetSocketAddress(0));
+ System.out.format("\nTest DatagramChannel to %s socket\n", family.name());
+ try (DatagramChannel dc = (family == UNSPEC) ?
+ DatagramChannel.open() : DatagramChannel.open(family)) {
+ dc.setOption(StandardSocketOption.SO_REUSEADDR, true)
+ .bind(new InetSocketAddress(0));
- // join group
- System.out.format("join %s @ %s\n", group.getHostAddress(),
- nif.getName());
- MembershipKey key = dc.join(group, nif);
+ // join group
+ System.out.format("join %s @ %s\n", group.getHostAddress(),
+ nif.getName());
+ MembershipKey key;
+ try {
+ key = dc.join(group, nif);
+ } catch (IllegalArgumentException iae) {
+ if (family == UNSPEC) {
+ System.out.println("Not supported");
+ return;
+ }
+ throw iae;
+ }
- // send message to group
- int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
- int id = sendDatagram(source, nif, group, port);
+ // send message to group
+ int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
+ int id = sendDatagram(source, nif, group, port);
- // receive message and check id matches
- receiveDatagram(dc, source, id);
-
- // exclude-mode filtering
-
- try {
- System.out.format("block %s\n", source.getHostAddress());
-
- // may throw UOE
- key.block(source);
- id = sendDatagram(source, nif, group, port);
- receiveDatagram(dc, null, id);
-
- // unblock source, send message, message should be received
- System.out.format("unblock %s\n", source.getHostAddress());
- key.unblock(source);
- id = sendDatagram(source, nif, group, port);
+ // receive message and check id matches
receiveDatagram(dc, source, id);
- } catch (UnsupportedOperationException x) {
- System.out.println("Exclude-mode filtering not supported!");
- }
- key.drop();
+ // exclude-mode filtering
- // include-mode filtering
+ try {
+ System.out.format("block %s\n", source.getHostAddress());
- InetAddress bogus = (group instanceof Inet6Address) ?
- InetAddress.getByName("fe80::1234") :
- InetAddress.getByName("1.2.3.4");
- System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
- nif.getName(), bogus.getHostAddress());
- try {
- // may throw UOE
- key = dc.join(group, nif, bogus);
+ // may throw UOE
+ key.block(source);
+ id = sendDatagram(source, nif, group, port);
+ receiveDatagram(dc, null, id);
- id = sendDatagram(source, nif, group, port);
- receiveDatagram(dc, null, id);
+ // unblock source, send message, message should be received
+ System.out.format("unblock %s\n", source.getHostAddress());
+ key.unblock(source);
+ id = sendDatagram(source, nif, group, port);
+ receiveDatagram(dc, source, id);
+ } catch (UnsupportedOperationException x) {
+ System.out.println("Exclude-mode filtering not supported!");
+ }
+ key.drop();
+
+ // include-mode filtering
+
+ InetAddress bogus = (group instanceof Inet6Address) ?
+ InetAddress.getByName("fe80::1234") :
+ InetAddress.getByName("1.2.3.4");
System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
- nif.getName(), source.getHostAddress());
- key = dc.join(group, nif, source);
+ nif.getName(), bogus.getHostAddress());
+ try {
+ // may throw UOE
+ key = dc.join(group, nif, bogus);
- id = sendDatagram(source, nif, group, port);
- receiveDatagram(dc, source, id);
- } catch (UnsupportedOperationException x) {
- System.out.println("Include-mode filtering not supported!");
+ id = sendDatagram(source, nif, group, port);
+ receiveDatagram(dc, null, id);
+
+ System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
+ nif.getName(), source.getHostAddress());
+ key = dc.join(group, nif, source);
+
+ id = sendDatagram(source, nif, group, port);
+ receiveDatagram(dc, source, id);
+ } catch (UnsupportedOperationException x) {
+ System.out.println("Include-mode filtering not supported!");
+ }
}
-
- // done
- dc.close();
}
public static void main(String[] args) throws IOException {
@@ -210,12 +226,14 @@ public class MulticastSendReceiveTests {
for (NetworkInterface nif: config.ip4Interfaces()) {
InetAddress source = config.ip4Addresses(nif).iterator().next();
- test(nif, ip4Group, source);
+ test(INET, nif, ip4Group, source);
+ test(UNSPEC, nif, ip4Group, source);
}
for (NetworkInterface nif: config.ip6Interfaces()) {
InetAddress source = config.ip6Addresses(nif).iterator().next();
- test(nif, ip6Group, source);
+ test(INET6, nif, ip6Group, source);
+ test(UNSPEC, nif, ip6Group, source);
}
}
}
diff --git a/jdk/test/java/nio/file/Files/FileAttributes.java b/jdk/test/java/nio/file/Files/FileAttributes.java
index bd799dc6b1e..d8aea7fe3ba 100644
--- a/jdk/test/java/nio/file/Files/FileAttributes.java
+++ b/jdk/test/java/nio/file/Files/FileAttributes.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 7017446
* @summary Unit test for java.nio.file.Files
* @library ..
*/
@@ -94,12 +94,6 @@ public class FileAttributes {
assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime"));
-
- map = Files.readAttributes(file,
- "basic:lastModifiedTime,lastAccessTime,ShouldNotExist");
- assertTrue(map.size() == 2);
- checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime"));
- checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime"));
}
// Exercise getAttribute/setAttribute/readAttributes on posix attributes
@@ -132,7 +126,7 @@ public class FileAttributes {
assertTrue(map.size() >= 12);
checkEqual(attrs.permissions(), map.get("permissions")); // check one
- map = Files.readAttributes(file, "posix:size,owner,ShouldNotExist");
+ map = Files.readAttributes(file, "posix:size,owner");
assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.owner(), map.get("owner"));
@@ -155,7 +149,7 @@ public class FileAttributes {
map = Files.readAttributes(file, "unix:*");
assertTrue(map.size() >= 20);
- map = Files.readAttributes(file, "unix:size,uid,gid,ShouldNotExist");
+ map = Files.readAttributes(file, "unix:size,uid,gid");
assertTrue(map.size() == 3);
checkEqual(map.get("size"),
Files.readAttributes(file, BasicFileAttributes.class).size());
@@ -206,14 +200,65 @@ public class FileAttributes {
assertTrue(map.size() >= 13);
checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one
- map = Files.readAttributes(file, "dos:size,hidden,ShouldNotExist");
+ map = Files.readAttributes(file, "dos:size,hidden");
assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.isHidden(), map.get("hidden"));
}
+ static void checkBadSet(Path file, String attribute, Object value)
+ throws IOException
+ {
+ try {
+ Files.setAttribute(file, attribute, 0);
+ throw new RuntimeException("IllegalArgumentException expected");
+ } catch (IllegalArgumentException ignore) { }
+ }
+
+ static void checkBadGet(Path file, String attribute) throws IOException {
+ try {
+ Files.getAttribute(file, attribute);
+ throw new RuntimeException("IllegalArgumentException expected");
+ } catch (IllegalArgumentException ignore) { }
+ }
+
+ static void checkBadRead(Path file, String attribute) throws IOException {
+ try {
+ Files.readAttributes(file, attribute);
+ throw new RuntimeException("IllegalArgumentException expected");
+ } catch (IllegalArgumentException ignore) { }
+ }
+
static void miscTests(Path file) throws IOException {
- // NPE tests
+ // unsupported views
+ try {
+ Files.setAttribute(file, "foo:bar", 0);
+ throw new RuntimeException("UnsupportedOperationException expected");
+ } catch (UnsupportedOperationException ignore) { }
+ try {
+ Files.getAttribute(file, "foo:bar");
+ throw new RuntimeException("UnsupportedOperationException expected");
+ } catch (UnsupportedOperationException ignore) { }
+ try {
+ Files.readAttributes(file, "foo:*");
+ throw new RuntimeException("UnsupportedOperationException expected");
+ } catch (UnsupportedOperationException ignore) { }
+
+ // bad args
+ checkBadSet(file, "", 0);
+ checkBadSet(file, "basic:", 0);
+ checkBadSet(file, "basic:foobar", 0);
+ checkBadGet(file, "");
+ checkBadGet(file, "basic:");
+ checkBadGet(file, "basic:foobar");
+ checkBadGet(file, "basic:size,lastModifiedTime");
+ checkBadGet(file, "basic:*");
+ checkBadRead(file, "");
+ checkBadRead(file, "basic:");
+ checkBadRead(file, "basic:foobar");
+ checkBadRead(file, "basic:size,foobar");
+
+ // nulls
try {
Files.getAttribute(file, null);
throw new RuntimeException("NullPointerException expected");
diff --git a/jdk/test/java/nio/file/WatchService/Basic.java b/jdk/test/java/nio/file/WatchService/Basic.java
index 2869a519f37..1b4c526dbd8 100644
--- a/jdk/test/java/nio/file/WatchService/Basic.java
+++ b/jdk/test/java/nio/file/WatchService/Basic.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 7017446
* @summary Unit test for java.nio.file.WatchService
* @library ..
* @run main/timeout=120 Basic
@@ -44,6 +44,8 @@ public class Basic {
static void checkKey(WatchKey key, Path dir) {
if (!key.isValid())
throw new RuntimeException("Key is not valid");
+ if (key.watchable() != dir)
+ throw new RuntimeException("Unexpected watchable");
}
static void takeExpectedKey(WatchService watcher, WatchKey expected) {
diff --git a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java
index a6af4192234..c8c07b4d8e4 100644
--- a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java
+++ b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java
@@ -141,9 +141,6 @@ public class Basic {
map = Files.readAttributes(file, "user:*");
if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
throw new RuntimeException("Unexpected attribute value");
- map = Files.readAttributes(file, "user:DoesNotExist");
- if (!map.isEmpty())
- throw new RuntimeException("Map expected to be empty");
}
static void miscTests(final Path file) throws IOException {
diff --git a/jdk/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java b/jdk/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java
new file mode 100644
index 00000000000..7113ba24647
--- /dev/null
+++ b/jdk/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/*
+ * Portions Copyright (c) 2011 IBM Corporation
+ */
+
+/*
+ * @test
+ * @bug 7014637
+ * @summary EnumSet's iterator.remove() can be resilient to set's modification.
+ * @author Neil Richards ,
+ */
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class LargeEnumIteratorRemoveResilience {
+ // enum with more than 64 values
+ private static enum LargeEnum {
+ e00, e01, e02, e03, e04, e05, e06, e07,
+ e08, e09, e0A, e0B, e0C, e0D, e0E, e0F,
+ e10, e11, e12, e13, e14, e15, e16, e17,
+ e18, e19, e1A, e1B, e1C, e1D, e1E, e1F,
+ e20, e21, e22, e23, e24, e25, e26, e27,
+ e28, e29, e2A, e2B, e2C, e2D, e2E, e2F,
+ e30, e31, e32, e33, e34, e35, e36, e37,
+ e38, e39, e3A, e3B, e3C, e3D, e3E, e3F,
+ e40, e41, e42, e43, e44, e45, e46, e47,
+ e48, e49, e4A, e4B, e4C, e4D, e4E, e4F,
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final Set set = EnumSet.noneOf(LargeEnum.class);
+
+ set.add(LargeEnum.e2D);
+ set.add(LargeEnum.e42);
+
+ final Iterator iterator = set.iterator();
+
+ int size = set.size();
+ LargeEnum element = iterator.next();
+
+ iterator.remove();
+ checkSetAfterRemoval(set, size, element);
+
+ size = set.size();
+ element = iterator.next();
+
+ set.remove(element);
+ checkSetAfterRemoval(set, size, element);
+
+ // The Java API declares that the behaviour here - to call
+ // iterator.remove() after the underlying collection has been
+ // modified - is "unspecified".
+ // However, in the case of iterators for EnumSet, it is easy to
+ // implement their remove() operation such that the set is
+ // unmodified if it is called for an element that has already been
+ // removed from the set - this being the naturally "resilient"
+ // behaviour.
+ iterator.remove();
+ checkSetAfterRemoval(set, size, element);
+ }
+
+ private static void checkSetAfterRemoval(final Set set,
+ final int origSize, final LargeEnum removedElement)
+ throws Exception {
+ if (set.size() != (origSize - 1)) {
+ throw new Exception("Test FAILED: Unexpected set size after removal; expected '" + (origSize - 1) + "' but found '" + set.size() + "'");
+ }
+ if (set.contains(removedElement)) {
+ throw new Exception("Test FAILED: Element returned from iterator unexpectedly still in set after removal.");
+ }
+ }
+}
diff --git a/jdk/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java b/jdk/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java
new file mode 100644
index 00000000000..e813a5cad3f
--- /dev/null
+++ b/jdk/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/*
+ * Portions Copyright (c) 2011 IBM Corporation
+ */
+
+/*
+ * @test
+ * @bug 7014637
+ * @summary EnumSet's iterator.remove() can be resilient to set's modification.
+ * @author Neil Richards ,
+ */
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class SmallEnumIteratorRemoveResilience {
+ // enum with less than 64 values
+ private static enum SmallEnum { e0, e1, e2 }
+
+ public static void main(final String[] args) throws Exception {
+ final Set set = EnumSet.noneOf(SmallEnum.class);
+
+ set.add(SmallEnum.e0);
+ set.add(SmallEnum.e1);
+
+ final Iterator iterator = set.iterator();
+
+ int size = set.size();
+ SmallEnum element = iterator.next();
+
+ iterator.remove();
+ checkSetAfterRemoval(set, size, element);
+
+ size = set.size();
+ element = iterator.next();
+
+ set.remove(element);
+ checkSetAfterRemoval(set, size, element);
+
+ // The Java API declares that the behaviour here - to call
+ // iterator.remove() after the underlying collection has been
+ // modified - is "unspecified".
+ // However, in the case of iterators for EnumSet, it is easy to
+ // implement their remove() operation such that the set is
+ // unmodified if it is called for an element that has already been
+ // removed from the set - this being the naturally "resilient"
+ // behaviour.
+ iterator.remove();
+ checkSetAfterRemoval(set, size, element);
+ }
+
+ private static void checkSetAfterRemoval(final Set set,
+ final int origSize, final SmallEnum removedElement)
+ throws Exception {
+ if (set.size() != (origSize - 1)) {
+ throw new Exception("Test FAILED: Unexpected set size after removal; expected '" + (origSize - 1) + "' but found '" + set.size() + "'");
+ }
+ if (set.contains(removedElement)) {
+ throw new Exception("Test FAILED: Element returned from iterator unexpectedly still in set after removal.");
+ }
+ }
+}
diff --git a/jdk/test/java/util/Locale/LocaleEnhanceTest.java b/jdk/test/java/util/Locale/LocaleEnhanceTest.java
index 0ee6ed24dca..23445d5afc0 100644
--- a/jdk/test/java/util/Locale/LocaleEnhanceTest.java
+++ b/jdk/test/java/util/Locale/LocaleEnhanceTest.java
@@ -43,7 +43,7 @@ import java.util.Set;
/**
* @test
- * @bug 6875847
+ * @bug 6875847 6992272 7002320 7015500 7023613
* @summary test API changes to Locale
*/
public class LocaleEnhanceTest extends LocaleTestFmwk {
@@ -83,7 +83,7 @@ public class LocaleEnhanceTest extends LocaleTestFmwk {
"en-Latn-US-NewYork", "en_US_NewYork_#Latn",
"en-Latn-US", "en_US_#Latn",
"en-Latn-NewYork", "en__NewYork_#Latn", // double underscore
- "en-Latn", "en_#Latn",
+ "en-Latn", "en__#Latn", // double underscore
"en-US-NewYork", "en_US_NewYork",
"en-US", "en_US",
"en-NewYork", "en__NewYork", // double underscore
@@ -1259,6 +1259,22 @@ public class LocaleEnhanceTest extends LocaleTestFmwk {
}
}
+ public void testBug7023613() {
+ String[][] testdata = {
+ {"en-Latn", "en__#Latn"},
+ {"en-u-ca-japanese", "en__#u-ca-japanese"},
+ };
+
+ for (String[] data : testdata) {
+ String in = data[0];
+ String expected = (data.length == 1) ? data[0] : data[1];
+
+ Locale loc = Locale.forLanguageTag(in);
+ String out = loc.toString();
+ assertEquals("Empty country field with non-empty script/extension with input: " + in, expected, out);
+ }
+ }
+
///
/// utility asserts
///
diff --git a/jdk/test/java/util/TreeMap/EmptyMapAndNulls.java b/jdk/test/java/util/TreeMap/EmptyMapAndNulls.java
new file mode 100644
index 00000000000..1642f74f1bc
--- /dev/null
+++ b/jdk/test/java/util/TreeMap/EmptyMapAndNulls.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 5045147
+ * @summary Test handling of null with empty Map
+ * @author Mike Duigou
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.lang.reflect.*;
+
+public class EmptyMapAndNulls {
+
+ @SuppressWarnings("rawtypes")
+ static void realMain(String[] args) throws Throwable {
+ // No comparator
+ Map comparable = new TreeMap<>();
+
+ // insert null into empty map (5045147 failure)
+ try {
+ comparable.put(null, "anything");
+ fail("null shouldn't be accepted");
+ } catch (NullPointerException failed) {
+ pass();
+ }
+
+ // insert non-null into empty map
+ try {
+ comparable.put("test", "anything");
+ pass();
+ } catch (NullPointerException failed) {
+ fail();
+ }
+
+ // insert null into non-empty map
+ try {
+ comparable.put(null, "anything");
+ fail("null shouldn't be accepted");
+ } catch (NullPointerException failed) {
+ pass();
+ }
+
+ // Comparator (String.CASE_INSENSITIVE_ORDER). Intentionally a raw type.
+ Map comparator = new TreeMap(String.CASE_INSENSITIVE_ORDER);
+
+ // insert null into empty map (5045147 failure)
+ try {
+ comparator.put(null, "anything");
+ fail("null shouldn't be accepted");
+ } catch (NullPointerException failed) {
+ pass();
+ }
+
+ // insert non-null into empty map
+ try {
+ comparator.put("test", "anything");
+ pass();
+ } catch (NullPointerException failed) {
+ fail();
+ }
+
+ // insert null into non-empty map
+ try {
+ comparator.put(null, "anything");
+ fail("null shouldn't be accepted");
+ } catch (NullPointerException failed) {
+ pass();
+ }
+
+ comparator.clear();
+
+ // insert non-String into empty map (5045147 failure)
+ try {
+ comparator.put(new Object(), "anything");
+ fail("Object shouldn't be accepted");
+ } catch (ClassCastException failed) {
+ pass();
+ }
+
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String msg) {System.out.println(msg); fail();}
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ static void check(boolean cond) {if (cond) pass(); else fail();}
+ static void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
diff --git a/jdk/test/javax/script/GetInterfaceTest.java b/jdk/test/javax/script/GetInterfaceTest.java
new file mode 100644
index 00000000000..d780a6db08b
--- /dev/null
+++ b/jdk/test/javax/script/GetInterfaceTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6960211
+ * @summary JavaScript engine allows creation of interface although methods not available.
+ */
+
+import javax.script.*;
+
+public class GetInterfaceTest {
+ public static void main(String[] args) throws Exception {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine engine = manager.getEngineByName("js");
+
+ if (engine == null) {
+ System.out.println("Warning: No engine engine found; test vacuously passes.");
+ return;
+ }
+
+ // don't define any function.
+ engine.eval("");
+
+ Runnable runnable = ((Invocable)engine).getInterface(Runnable.class);
+ if (runnable != null) {
+ throw new RuntimeException("runnable is not null!");
+ }
+
+ // now define "run"
+ engine.eval("function run() { println('this is run function'); }");
+ runnable = ((Invocable)engine).getInterface(Runnable.class);
+ // should not return null now!
+ runnable.run();
+
+ // define only one method of "Foo2"
+ engine.eval("function bar() { println('bar function'); }");
+ Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class);
+ if (foo2 != null) {
+ throw new RuntimeException("foo2 is not null!");
+ }
+
+ // now define other method of "Foo2"
+ engine.eval("function bar2() { println('bar2 function'); }");
+ foo2 = ((Invocable)engine).getInterface(Foo2.class);
+ foo2.bar();
+ foo2.bar2();
+ }
+
+ interface Foo {
+ public void bar();
+ }
+
+ interface Foo2 extends Foo {
+ public void bar2();
+ }
+}
diff --git a/jdk/test/javax/swing/JOptionPane/6464022/bug6464022.java b/jdk/test/javax/swing/JOptionPane/6464022/bug6464022.java
new file mode 100644
index 00000000000..9554ae9828e
--- /dev/null
+++ b/jdk/test/javax/swing/JOptionPane/6464022/bug6464022.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6464022
+ * @summary Memory leak in JOptionPane.createDialog
+ * @author Pavel Porvatov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug6464022
+ */
+
+import javax.swing.*;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+public class bug6464022 {
+ private static JOptionPane pane;
+
+ public static void main(String[] args) throws Exception {
+ final List> references = new ArrayList>();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ pane = new JOptionPane(null, JOptionPane.UNDEFINED_CONDITION);
+
+ for (int i = 0; i < 10; i++) {
+ JDialog dialog = pane.createDialog(null, "Test " + i);
+
+ references.add(new WeakReference(dialog));
+
+ dialog.dispose();
+
+ System.out.println("Disposing Dialog:" + dialog.hashCode());
+ }
+ }
+ });
+
+ Util.generateOOME();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ int allocatedCount = 0;
+
+ for (WeakReference ref : references) {
+ if (ref.get() != null) {
+ allocatedCount++;
+
+ System.out.println(ref.get().hashCode() + " is still allocated");
+ }
+ }
+
+ if (allocatedCount > 0) {
+ throw new RuntimeException("Some dialogs still exist in memory. Test failed");
+ } else {
+ System.out.println("All dialogs were GCed. Test passed.");
+ }
+ }
+ });
+ }
+}
diff --git a/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java b/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java
index 781f57d3872..698dc00e22f 100644
--- a/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java
+++ b/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java
@@ -26,6 +26,8 @@
* @bug 6795356
* @summary Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc
* @author Alexander Potochkin
+ * @library ../../regtesthelpers
+ * @build Util
* @run main bug6795356
*/
@@ -58,43 +60,11 @@ public class bug6795356 {
weakRef = new WeakReference(domain);
domain = null;
- // Generate OutOfMemory and check the weak ref
- generateOOME();
+ Util.generateOOME();
if (weakRef.get() != null) {
throw new RuntimeException("Memory leak found!");
}
System.out.println("Test passed");
}
-
- static void generateOOME() {
- List bigLeak = new LinkedList();
- boolean oome = false;
- System.out.print("Filling the heap");
- try {
- for(int i = 0; true ; i++) {
- // Now, use up all RAM
- bigLeak.add(new byte[1024 * 1024]);
- System.out.print(".");
-
- // Give the GC a change at that weakref
- if (i % 10 == 0) {
- System.gc();
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- } catch (OutOfMemoryError e) {
- bigLeak = null;
- oome = true;
- }
- System.out.println("");
- if (!oome) {
- throw new RuntimeException("Problem with test case - never got OOME");
- }
- System.out.println("Got OOME");
- }
}
diff --git a/jdk/test/javax/swing/regtesthelpers/Util.java b/jdk/test/javax/swing/regtesthelpers/Util.java
index 5da14b9396a..76217ae8687 100644
--- a/jdk/test/javax/swing/regtesthelpers/Util.java
+++ b/jdk/test/javax/swing/regtesthelpers/Util.java
@@ -24,6 +24,8 @@
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
+import java.util.LinkedList;
+import java.util.List;
/**
* This class contains utilities useful for regression testing.
@@ -72,4 +74,46 @@ public class Util {
return true;
}
+
+ /**
+ * Fills the heap until OutOfMemoryError occurs. This method is useful for
+ * WeakReferences removing.
+ */
+ public static void generateOOME() {
+ List bigLeak = new LinkedList();
+
+ boolean oome = false;
+
+ System.out.print("Filling the heap");
+
+ try {
+ for(int i = 0; true ; i++) {
+ // Now, use up all RAM
+ bigLeak.add(new byte[1024 * 1024]);
+
+ System.out.print(".");
+
+ // Give the GC a change at that weakref
+ if (i % 10 == 0) {
+ System.gc();
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } catch (OutOfMemoryError e) {
+ bigLeak = null;
+ oome = true;
+ }
+
+ System.out.println("");
+
+ if (!oome) {
+ throw new RuntimeException("Problem with test case - never got OOME");
+ }
+
+ System.out.println("Got OOME");
+ }
}
diff --git a/jdk/test/sun/java2d/pipe/Test7027667.java b/jdk/test/sun/java2d/pipe/Test7027667.java
new file mode 100644
index 00000000000..08f478f60b1
--- /dev/null
+++ b/jdk/test/sun/java2d/pipe/Test7027667.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/**
+ * @test
+ * @bug 7027667, 7023591
+ *
+ * @summary Verifies that aa clipped rectangles are drawn, not filled.
+ *
+ * @run main Test7027667
+ */
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import static java.awt.RenderingHints.*;
+
+public class Test7027667 {
+ public static void main(String[] args) throws Exception {
+ BufferedImage bImg = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = (Graphics2D) bImg.getGraphics();
+ g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
+ g2d.setClip(new Ellipse2D.Double(0, 0, 100, 100));
+ g2d.drawRect(10, 10, 100, 100);
+ if (new Color(bImg.getRGB(50, 50)).equals(Color.white)) {
+ throw new Exception("Rectangle should be drawn, not filled");
+ }
+ }
+}
diff --git a/jdk/test/sun/java2d/pisces/Renderer/Test7019861.java b/jdk/test/sun/java2d/pisces/Renderer/Test7019861.java
new file mode 100644
index 00000000000..7c262b961cf
--- /dev/null
+++ b/jdk/test/sun/java2d/pisces/Renderer/Test7019861.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/**
+ * @test
+ * @bug 7019861
+ *
+ * @summary Verifies that the last scanline isn't skipped when doing
+ * antialiased rendering.
+ *
+ * @run main Test7019861
+ */
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Path2D;
+import java.awt.image.BufferedImage;
+import java.util.Arrays;
+
+import static java.awt.RenderingHints.*;
+
+public class Test7019861 {
+
+ public static void main(String[] argv) throws Exception {
+ BufferedImage im = getWhiteImage(30, 30);
+ Graphics2D g2 = (Graphics2D)im.getGraphics();
+ g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE);
+ g2.setStroke(new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+ g2.setBackground(Color.white);
+ g2.setColor(Color.black);
+
+ Path2D p = getPath(0, 0, 20);
+ g2.draw(p);
+
+ if (!(new Color(im.getRGB(20, 19))).equals(Color.black)) {
+ throw new Exception("This pixel should be black");
+ }
+ }
+
+ private static Path2D getPath(int x, int y, int len) {
+ Path2D p = new Path2D.Double();
+ p.moveTo(x, y);
+ p.quadTo(x + len, y, x + len, y + len);
+ return p;
+ }
+
+ private static BufferedImage getWhiteImage(int w, int h) {
+ BufferedImage ret = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ final int[] white = new int[w * h];
+ Arrays.fill(white, 0xffffff);
+ ret.setRGB(0, 0, w, h, white, 0, w);
+ return ret;
+ }
+}
diff --git a/jdk/test/sun/nio/cs/TestIBM1364.java b/jdk/test/sun/nio/cs/TestIBM1364.java
new file mode 100644
index 00000000000..78912bdf519
--- /dev/null
+++ b/jdk/test/sun/nio/cs/TestIBM1364.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+
+/* @test
+ @bug 6803681
+ @summary Test IBM1364
+ */
+
+import java.util.Arrays;
+import java.nio.*;
+import java.nio.charset.*;
+
+public class TestIBM1364 {
+ private static String c2bNRStr = "\u00AD\u00B7\u2015\u223C\u2299\uFF5E";
+ private static byte[] c2bNRBytes = new byte[] {
+ (byte)0x0e,
+ (byte)0x41, (byte)0x48,
+ (byte)0x41, (byte)0x43,
+ (byte)0x41, (byte)0x49,
+ (byte)0x42, (byte)0xa1,
+ (byte)0x49, (byte)0x6f,
+ (byte)0x49, (byte)0x54,
+ (byte)0x0f };
+
+ // end at SO
+ private static String mixedStr = "\u008d\u008e\u0020\u3000\u3001\u71ba\u3164\u0088\ue757";
+ private static byte[] mixedBytes = new byte[] {
+ (byte)0x09,
+ (byte)0x0a,
+ (byte)0x40,
+ (byte)0x0e,
+ (byte)0x40, (byte)0x40,
+ (byte)0x41, (byte)0x41,
+ (byte)0x6c, (byte)0x45,
+ (byte)0x84, (byte)0x41,
+ (byte)0x0f,
+ (byte)0x28,
+ (byte)0x0e,
+ (byte)0xdd, (byte)0xfd,
+ (byte)0x0f };
+
+ // end at SI
+ private static String mixedStr2 = "\u008d\u008e\u0020\u3000\u3001\u71ba\u3164\u0088";
+ private static byte[] mixedBytes2 = new byte[] {
+ (byte)0x09,
+ (byte)0x0a,
+ (byte)0x40,
+ (byte)0x0e,
+ (byte)0x40, (byte)0x40,
+ (byte)0x41, (byte)0x41,
+ (byte)0x6c, (byte)0x45,
+ (byte)0x84, (byte)0x41,
+ (byte)0x0f,
+ (byte)0x28 };
+
+ private static byte[][] malformedBytes = {
+ { (byte)0x0e,
+ (byte)0x039, (byte)0x40,
+ (byte)0x0f
+ },
+ { (byte)0x0e,
+ (byte)0x039, (byte)0x42,
+ (byte)0x0f
+ },
+ { (byte)0x0e,
+ (byte)0x040, (byte)0x41,
+ (byte)0x0f
+ },
+ { (byte)0x0e,
+ (byte)0x040, (byte)0xee,
+ (byte)0x0f
+ },
+ { (byte)0x0e,
+ (byte)0x0ef, (byte)0x30,
+ (byte)0x0f
+ },
+ { (byte)0x0e,
+ (byte)0x0ff, (byte)0x41,
+ (byte)0x0f
+ }
+ };
+
+ private static byte[][] unmappedBytes = {
+ { (byte)0x0e,
+ (byte)0x06c, (byte)0x46,
+ (byte)0x0f,
+ },
+ { (byte)0x0e,
+ (byte)0x078, (byte)0x46,
+ (byte)0x0f,
+ },
+ { (byte)0x0e,
+ (byte)0x083, (byte)0xfe,
+ (byte)0x0f,
+ },
+ { (byte)0xfa },
+ { (byte)0xfe },
+ };
+
+ public static void main(String[] args) throws Exception {
+ if (!(Arrays.equals(mixedStr.getBytes("cp1364"), mixedBytes)) ||
+ !mixedStr.equals(new String(mixedBytes, "cp1364")))
+ throw new RuntimeException("cp1364 failed on mixed!");
+
+ if (!(Arrays.equals(mixedStr2.getBytes("cp1364"), mixedBytes2)) ||
+ !mixedStr2.equals(new String(mixedBytes2, "cp1364")))
+ throw new RuntimeException("cp1364 failed on mixed!");
+
+ if (!(Arrays.equals(c2bNRStr.getBytes("cp1364"), c2bNRBytes)) ||
+ c2bNRStr.equals(new String(c2bNRBytes, "cp1364")))
+ throw new RuntimeException("cp1364 failed on c2bNR!");
+
+ ByteBuffer bb = ByteBuffer.allocateDirect(mixedBytes.length);
+ bb.put(mixedBytes).flip();
+ CharBuffer cb = Charset.forName("ibm1364").decode(bb);
+ if (!mixedStr.equals(new String(cb.toString())))
+ throw new RuntimeException("cp1364 failed on direct decod()!");
+
+ bb = ByteBuffer.allocateDirect(mixedBytes2.length);
+ bb.put(mixedBytes2).flip();
+ cb = Charset.forName("ibm1364").decode(bb);
+ if (!mixedStr2.equals(new String(cb.toString())))
+ throw new RuntimeException("cp1364 failed on direct decod()!");
+
+ cb = ByteBuffer.allocateDirect(mixedStr.length() * 2).asCharBuffer();
+ cb.put(mixedStr.toCharArray()).flip();
+ bb = Charset.forName("x-ibm1364").encode(cb);
+ if (!(Arrays.equals(Arrays.copyOf(bb.array(), bb.limit()), mixedBytes)))
+ throw new RuntimeException("cp1364 failed on direct encode()!");
+
+ cb = ByteBuffer.allocateDirect(mixedStr2.length() * 2).asCharBuffer();
+ cb.put(mixedStr2.toCharArray()).flip();
+ bb = Charset.forName("x-ibm1364").encode(cb);
+ if (!(Arrays.equals(Arrays.copyOf(bb.array(), bb.limit()), mixedBytes2)))
+ throw new RuntimeException("cp1364 failed on direct encode()!");
+
+ // malformed
+ cb = CharBuffer.allocate(1024);
+ CharBuffer cbd = ByteBuffer.allocateDirect(1024).asCharBuffer();
+ CharsetDecoder dec = Charset.forName("x-ibm1364").newDecoder();
+ for (byte[] ba:malformedBytes) {
+ cb.clear();
+ dec.reset();
+ if (!dec.reset().decode(ByteBuffer.wrap(ba), cb, true).isMalformed() ||
+ !dec.reset().decode(ByteBuffer.wrap(ba), cbd, true).isMalformed())
+ throw new RuntimeException("cp1364 failed on decode()/malformed!");
+ }
+
+ //unmappable
+ for (byte[] ba:unmappedBytes) {
+ cb.clear();
+ dec.reset();
+ if (!dec.reset().decode(ByteBuffer.wrap(ba), cb, true).isUnmappable() ||
+ !dec.reset().decode(ByteBuffer.wrap(ba), cbd, true).isUnmappable())
+ throw new RuntimeException("cp1364 failed on decode()/unmappable!");
+ }
+
+ //overflow
+ cb.limit(mixedStr.length() - 1);
+ cbd.limit(mixedStr.length() - 1);
+ if (!dec.reset().decode(ByteBuffer.wrap(mixedBytes), cb, true).isOverflow() ||
+ !dec.reset().decode(ByteBuffer.wrap(mixedBytes), cbd, true).isOverflow())
+ throw new RuntimeException("cp1364 failed on decode()/overflow!");
+
+ CharsetEncoder enc = Charset.forName("x-ibm1364").newEncoder();
+ // last "0x0f" is from flush()
+ bb = ByteBuffer.allocate(mixedBytes.length - 2);
+ ByteBuffer bbd = ByteBuffer.allocateDirect(mixedBytes.length - 2);
+ if (!enc.reset()
+ .encode(CharBuffer.wrap(mixedStr.toCharArray()), bb, true)
+ .isOverflow() ||
+ !enc.reset()
+ .encode(CharBuffer.wrap(mixedStr.toCharArray()), bbd, true)
+ .isOverflow())
+ throw new RuntimeException("cp1364 failed on encode()/overflow!");
+
+ // flush() overflow
+ bb = ByteBuffer.allocate(mixedBytes.length - 1);
+ bbd = ByteBuffer.allocateDirect(mixedBytes.length - 1);
+
+ enc.reset().encode(CharBuffer.wrap(mixedStr.toCharArray()), bb, true);
+ enc.reset().encode(CharBuffer.wrap(mixedStr.toCharArray()), bbd, true);
+
+ if (!enc.flush(bb).isOverflow() ||
+ !enc.flush(bbd).isOverflow())
+ throw new RuntimeException("cp1364 failed on encode()/flush()/overflow!");
+ }
+}
diff --git a/jdk/test/sun/security/mscapi/access.policy b/jdk/test/sun/security/mscapi/access.policy
index 27e6692027c..22bf290bd8f 100644
--- a/jdk/test/sun/security/mscapi/access.policy
+++ b/jdk/test/sun/security/mscapi/access.policy
@@ -3,7 +3,7 @@ grant {
permission java.lang.RuntimePermission
"accessClassInPackage.sun.*";
- permission java.lang.RuntimePermission "loadLibrary.sunmscapi";
+ permission java.lang.RuntimePermission "loadLibrary.*";
permission java.util.PropertyPermission "os.arch", "read";
diff --git a/jdk/test/sun/security/mscapi/noaccess.policy b/jdk/test/sun/security/mscapi/noaccess.policy
index 8cda681cfed..e4260cf5070 100644
--- a/jdk/test/sun/security/mscapi/noaccess.policy
+++ b/jdk/test/sun/security/mscapi/noaccess.policy
@@ -3,7 +3,7 @@ grant {
permission java.lang.RuntimePermission
"accessClassInPackage.sun.*";
- permission java.lang.RuntimePermission "loadLibrary.sunmscapi";
+ permission java.lang.RuntimePermission "loadLibrary.*";
permission java.util.PropertyPermission "os.arch", "read";
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java b/jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java
index dcfb98b48c4..2ffdad9ac02 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/GetInstance.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -23,8 +23,9 @@
/*
* @test
- * @bug 4898428
+ * @bug 4898428 7022855
* @summary verify getInstance() works using Provider.getService()
+ * Export "PKIX" as the standard algorithm name of KeyManagerFactory
* @author Andreas Sterbenz
*/
@@ -61,6 +62,20 @@ public class GetInstance {
kmf = KeyManagerFactory.getInstance("SunX509", p);
same(p, kmf.getProvider());
+ kmf = KeyManagerFactory.getInstance("NewSunX509");
+ same(p, kmf.getProvider());
+ kmf = KeyManagerFactory.getInstance("NewSunX509", "SunJSSE");
+ same(p, kmf.getProvider());
+ kmf = KeyManagerFactory.getInstance("NewSunX509", p);
+ same(p, kmf.getProvider());
+
+ kmf = KeyManagerFactory.getInstance("PKIX");
+ same(p, kmf.getProvider());
+ kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");
+ same(p, kmf.getProvider());
+ kmf = KeyManagerFactory.getInstance("PKIX", p);
+ same(p, kmf.getProvider());
+
TrustManagerFactory tmf;
tmf = TrustManagerFactory.getInstance("SunX509");
same(p, tmf.getProvider());
@@ -69,6 +84,34 @@ public class GetInstance {
tmf = TrustManagerFactory.getInstance("SunX509", p);
same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("PKIX");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("PKIX", p);
+ same(p, tmf.getProvider());
+
+ tmf = TrustManagerFactory.getInstance("SunPKIX");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("SunPKIX", "SunJSSE");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("SunPKIX", p);
+ same(p, tmf.getProvider());
+
+ tmf = TrustManagerFactory.getInstance("X509");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("X509", "SunJSSE");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("X509", p);
+ same(p, tmf.getProvider());
+
+ tmf = TrustManagerFactory.getInstance("X.509");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("X.509", "SunJSSE");
+ same(p, tmf.getProvider());
+ tmf = TrustManagerFactory.getInstance("X.509", p);
+ same(p, tmf.getProvider());
+
testComSun();
long stop = System.currentTimeMillis();
diff --git a/jdk/test/tools/launcher/MiscTests.java b/jdk/test/tools/launcher/MiscTests.java
index 654a56a01f4..1d7fcf9514b 100644
--- a/jdk/test/tools/launcher/MiscTests.java
+++ b/jdk/test/tools/launcher/MiscTests.java
@@ -23,8 +23,8 @@
/*
* @test
- * @bug 6856415 6981001
- * @summary Miscellaneous tests, Exceptions, EnsureJRE etc.
+ * @bug 6856415
+ * @summary Miscellaneous tests, Exceptions
* @compile -XDignore.symbol.file MiscTests.java TestHelper.java
* @run main MiscTests
*/
@@ -32,9 +32,6 @@
import java.io.File;
import java.io.FileNotFoundException;
-import java.util.HashMap;
-import java.util.Map;
-
public class MiscTests {
@@ -67,22 +64,9 @@ public class MiscTests {
System.out.println(tr.status);
}
}
- // 6981001 : Check EnsureJreInstallation is ok, note we cannot
- // thoroughly test this function, we simply do our best.
- static void test6981001() {
- if (TestHelper.is64Bit || !TestHelper.isWindows) {
- return;
- }
- Map env = new HashMap();
- env.put("_JAVA_LAUNCHER_DEBUG", "true");
- TestHelper.TestResult tr = TestHelper.doExec(env, TestHelper.javaCmd);
- if (!tr.contains(TestHelper.JAVAHOME + "\\lib\\bundles")) {
- System.out.println(tr.status);
- }
- }
+
public static void main(String... args) {
test6856415();
- test6981001();
if (TestHelper.testExitValue != 0) {
throw new Error(TestHelper.testExitValue + " tests failed");
}
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 695f4d3b2ce..3dc82c74e43 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -109,3 +109,4 @@ d7225b476a5d1aebffb8827e7c72ba2e1651f4e7 jdk7-b128
e3d011d59a33acef79eff7523bef069557e91002 jdk7-b132
e77e98f936e83d94c9b56cc7af218dc822a06122 jdk7-b133
3d7acdbb72cab55deedfd35f60d4732abc9d6ac4 jdk7-b134
+9d0a61ac567b983da7cc8f4a7030f2245bb6dbab jdk7-b135
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java
index 9db6e97bb3d..bbac0b65cb1 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, 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
@@ -305,11 +305,7 @@ public class ClassUseWriter extends SubWriterHolderWriter {
tr.addContent(tdFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
- if (pkg != null) {
- addSummaryComment(pkg, tdLast);
- } else {
- tdLast.addContent(getSpace());
- }
+ addSummaryComment(pkg, tdLast);
tr.addContent(tdLast);
tbody.addContent(tr);
}
@@ -355,10 +351,7 @@ public class ClassUseWriter extends SubWriterHolderWriter {
contentTree.addContent(tdFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
- if (pkg != null)
- addSummaryComment(pkg, tdLast);
- else
- tdLast.addContent(getSpace());
+ addSummaryComment(pkg, tdLast);
contentTree.addContent(tdLast);
}
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java
index e162075a636..ba6f921e61c 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java
@@ -283,23 +283,32 @@ public class HelpWriter extends HtmlDocletWriter {
Content framePara = HtmlTree.P(line26);
liFrame.addContent(framePara);
ul.addContent(liFrame);
+ Content allclassesHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
+ getResource("doclet.All_Classes"));
+ Content liAllClasses = HtmlTree.LI(HtmlStyle.blockList, allclassesHead);
+ Content line27 = getResource("doclet.Help_line_27",
+ getHyperLinkString("allclasses-noframe.html",
+ configuration.getText("doclet.All_Classes")));
+ Content allclassesPara = HtmlTree.P(line27);
+ liAllClasses.addContent(allclassesPara);
+ ul.addContent(liAllClasses);
Content sHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
getResource("doclet.Serialized_Form"));
Content liSerial = HtmlTree.LI(HtmlStyle.blockList, sHead);
- Content line27 = getResource("doclet.Help_line_27");
- Content serialPara = HtmlTree.P(line27);
+ Content line28 = getResource("doclet.Help_line_28");
+ Content serialPara = HtmlTree.P(line28);
liSerial.addContent(serialPara);
ul.addContent(liSerial);
Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
getResource("doclet.Constants_Summary"));
Content liConst = HtmlTree.LI(HtmlStyle.blockList, constHead);
- Content line28 = getResource("doclet.Help_line_28");
- Content constPara = HtmlTree.P(line28);
+ Content line29 = getResource("doclet.Help_line_29");
+ Content constPara = HtmlTree.P(line29);
liConst.addContent(constPara);
ul.addContent(liConst);
Content divContent = HtmlTree.DIV(HtmlStyle.contentContainer, ul);
- Content line29 = HtmlTree.EM(getResource("doclet.Help_line_29"));
- divContent.addContent(line29);
+ Content line30 = HtmlTree.EM(getResource("doclet.Help_line_30"));
+ divContent.addContent(line30);
contentTree.addContent(divContent);
}
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java
index 5bea2d75204..4e9019a1d98 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, 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
@@ -246,10 +246,7 @@ public class PackageUseWriter extends SubWriterHolderWriter {
contentTree.addContent(tdFirst);
HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
tdLast.addStyle(HtmlStyle.colLast);
- if (pkg != null)
- addSummaryComment(pkg, tdLast);
- else
- tdLast.addContent(getSpace());
+ addSummaryComment(pkg, tdLast);
contentTree.addContent(tdLast);
}
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
index 16fdd9497de..b59771f2c42 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
@@ -167,7 +167,7 @@ doclet.Window_Help_title=API Help
doclet.Help_line_1=How This API Document Is Organized
doclet.Help_line_2=This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
doclet.Help_line_3=The {0} page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.
-doclet.Help_line_4=Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:
+doclet.Help_line_4=Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:
doclet.Help_line_5=Class/Interface
doclet.Help_line_6=Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
doclet.Help_line_7=Class inheritance diagram
@@ -190,9 +190,10 @@ doclet.Help_line_23=Prev/Next
doclet.Help_line_24=These links take you to the next or previous class, interface, package, or related page.
doclet.Help_line_25=Frames/No Frames
doclet.Help_line_26=These links show and hide the HTML frames. All pages are available with or without frames.
-doclet.Help_line_27=Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
-doclet.Help_line_28=The Constant Field Values page lists the static final fields and their values.
-doclet.Help_line_29=This help file applies to API documentation generated using the standard doclet.
+doclet.Help_line_27=The {0} link shows all classes and interfaces except non-static nested types.
+doclet.Help_line_28=Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
+doclet.Help_line_29=The Constant Field Values page lists the static final fields and their values.
+doclet.Help_line_30=This help file applies to API documentation generated using the standard doclet.
doclet.Help_enum_line_1=Each enum has its own separate page with the following sections:
doclet.Help_enum_line_2=Enum declaration
doclet.Help_enum_line_3=Enum description
diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
index 07e39a8c3bd..17f894a09a0 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -129,19 +129,11 @@ public class JavacTaskImpl extends JavacTask {
public Boolean call() {
if (!used.getAndSet(true)) {
- beginContext();
+ initContext();
notYetEntered = new HashMap();
- try {
- compilerMain.setFatalErrors(true);
- result = compilerMain.compile(args, context, fileObjects, processors);
- } finally {
- endContext();
- }
- compilerMain = null;
- args = null;
- context = null;
- fileObjects = null;
- notYetEntered = null;
+ compilerMain.setFatalErrors(true);
+ result = compilerMain.compile(args, context, fileObjects, processors);
+ cleanup();
return result == 0;
} else {
throw new IllegalStateException("multiple calls to method 'call'");
@@ -163,8 +155,11 @@ public class JavacTaskImpl extends JavacTask {
}
private void prepareCompiler() throws IOException {
- if (!used.getAndSet(true)) {
- beginContext();
+ if (used.getAndSet(true)) {
+ if (compiler == null)
+ throw new IllegalStateException();
+ } else {
+ initContext();
compilerMain.setOptions(Options.instance(context));
compilerMain.filenames = new ListBuffer();
List filenames = compilerMain.processArgs(CommandLine.parse(args));
@@ -185,13 +180,12 @@ public class JavacTaskImpl extends JavacTask {
}
}
- private void beginContext() {
+ private void initContext() {
context.put(JavacTaskImpl.class, this);
if (context.get(TaskListener.class) != null)
context.put(TaskListener.class, (TaskListener)null);
if (taskListener != null)
context.put(TaskListener.class, wrap(taskListener));
- tool.beginContext(context);
//initialize compiler's default locale
JavacMessages.instance(context).setCurrentLocale(locale);
}
@@ -218,8 +212,15 @@ public class JavacTaskImpl extends JavacTask {
};
}
- private void endContext() {
- tool.endContext();
+ void cleanup() {
+ if (compiler != null)
+ compiler.close();
+ compiler = null;
+ compilerMain = null;
+ args = null;
+ context = null;
+ fileObjects = null;
+ notYetEntered = null;
}
/**
@@ -446,12 +447,12 @@ public class JavacTaskImpl extends JavacTask {
}
if (genList.isEmpty()) {
compiler.reportDeferredDiagnostics();
- compiler.log.flush();
- endContext();
+ cleanup();
}
}
finally {
- compiler.log.flush();
+ if (compiler != null)
+ compiler.log.flush();
}
return results;
}
diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java
index 354f5fad5fd..23405f6e1d4 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java
@@ -152,36 +152,6 @@ public final class JavacTool implements JavaCompiler {
return new JavacFileManager(context, true, charset);
}
- private boolean compilationInProgress = false;
-
- /**
- * Register that a compilation is about to start.
- */
- void beginContext(Context context) {
- if (compilationInProgress)
- throw new IllegalStateException("Compilation in progress");
- compilationInProgress = true;
- final JavaFileManager givenFileManager = context.get(JavaFileManager.class);
- context.put(JavaFileManager.class, (JavaFileManager)null);
- context.put(JavaFileManager.class, new Context.Factory() {
- public JavaFileManager make(Context c) {
- if (givenFileManager != null) {
- c.put(JavaFileManager.class, givenFileManager);
- return givenFileManager;
- } else {
- return new JavacFileManager(c, true, null);
- }
- }
- });
- }
-
- /**
- * Register that a compilation is completed.
- */
- void endContext() {
- compilationInProgress = false;
- }
-
public JavacTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener super JavaFileObject> diagnosticListener,
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
index b4bb52cfbf9..3ecbf5a3b89 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
@@ -131,6 +131,12 @@ public enum Source {
public boolean allowMulticatch() {
return compareTo(JDK1_7) >= 0;
}
+ public boolean allowImprovedRethrowAnalysis() {
+ return compareTo(JDK1_7) >= 0;
+ }
+ public boolean allowImprovedCatchAnalysis() {
+ return compareTo(JDK1_7) >= 0;
+ }
public boolean allowEnums() {
return compareTo(JDK1_5) >= 0;
}
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
index 46c1982b40e..2f224ebd27b 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -3004,6 +3004,30 @@ public class Attr extends JCTree.Visitor {
throw new AssertionError();
}
+ /**
+ * Attribute an env for either a top level tree or class declaration.
+ */
+ public void attrib(Env env) {
+ if (env.tree.getTag() == JCTree.TOPLEVEL)
+ attribTopLevel(env);
+ else
+ attribClass(env.tree.pos(), env.enclClass.sym);
+ }
+
+ /**
+ * Attribute a top level tree. These trees are encountered when the
+ * package declaration has annotations.
+ */
+ public void attribTopLevel(Env env) {
+ JCCompilationUnit toplevel = env.toplevel;
+ try {
+ annotate.flush();
+ chk.validateAnnotations(toplevel.packageAnnotations, toplevel.packge);
+ } catch (CompletionFailure ex) {
+ chk.completionError(toplevel.pos(), ex);
+ }
+ }
+
/** Main method: attribute class definition associated with given class symbol.
* reporting completion failures at the given position.
* @param pos The source position at which completion errors are to be
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
index 89191201de1..8b07d8e9040 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -190,7 +190,8 @@ public class Flow extends TreeScanner {
private final Resolve rs;
private Env attrEnv;
private Lint lint;
- private final boolean allowRethrowAnalysis;
+ private final boolean allowImprovedRethrowAnalysis;
+ private final boolean allowImprovedCatchAnalysis;
public static Flow instance(Context context) {
Flow instance = context.get(flowKey);
@@ -209,7 +210,8 @@ public class Flow extends TreeScanner {
lint = Lint.instance(context);
rs = Resolve.instance(context);
Source source = Source.instance(context);
- allowRethrowAnalysis = source.allowMulticatch();
+ allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
+ allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
}
/** A flag that indicates whether the last statement could
@@ -1046,7 +1048,9 @@ public class Flow extends TreeScanner {
}
}
scanStat(tree.body);
- List thrownInTry = thrown;
+ List thrownInTry = allowImprovedCatchAnalysis ?
+ chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
+ thrown;
thrown = thrownPrev;
caught = caughtPrev;
boolean aliveEnd = alive;
@@ -1081,16 +1085,7 @@ public class Flow extends TreeScanner {
ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType))
continue;
- if (chk.subset(exc, caughtInTry)) {
- log.error(l.head.pos(),
- "except.already.caught", exc);
- } else if (!chk.isUnchecked(l.head.pos(), exc) &&
- exc.tsym != syms.throwableType.tsym &&
- exc.tsym != syms.exceptionType.tsym &&
- !chk.intersects(exc, thrownInTry)) {
- log.error(l.head.pos(),
- "except.never.thrown.in.try", exc);
- }
+ checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
caughtInTry = chk.incl(exc, caughtInTry);
}
}
@@ -1154,6 +1149,29 @@ public class Flow extends TreeScanner {
uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
}
+ void checkCaughtType(DiagnosticPosition pos, Type exc, List thrownInTry, List caughtInTry) {
+ if (chk.subset(exc, caughtInTry)) {
+ log.error(pos, "except.already.caught", exc);
+ } else if (!chk.isUnchecked(pos, exc) &&
+ exc.tsym != syms.throwableType.tsym &&
+ exc.tsym != syms.exceptionType.tsym &&
+ !chk.intersects(exc, thrownInTry)) {
+ log.error(pos, "except.never.thrown.in.try", exc);
+ } else if (allowImprovedCatchAnalysis) {
+ List catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
+ // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
+ // unchecked exception, the result list would not be empty, as the augmented
+ // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
+ // exception, that would have been covered in the branch above
+ if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty()) {
+ String key = catchableThrownTypes.length() == 1 ?
+ "unreachable.catch" :
+ "unreachable.catch.1";
+ log.warning(pos, key, catchableThrownTypes);
+ }
+ }
+ }
+
public void visitConditional(JCConditional tree) {
scanCond(tree.cond);
Bits initsBeforeElse = initsWhenFalse;
@@ -1238,7 +1256,7 @@ public class Flow extends TreeScanner {
sym.kind == VAR &&
(sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
preciseRethrowTypes.get(sym) != null &&
- allowRethrowAnalysis) {
+ allowImprovedRethrowAnalysis) {
for (Type t : preciseRethrowTypes.get(sym)) {
markThrown(tree, t);
}
diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
index 8e89af024de..ff10fd3ed36 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java
@@ -89,7 +89,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
private FSInfo fsInfo;
- private boolean useZipFileIndex;
+ private boolean contextUseOptimizedZip;
private ZipFileIndexCache zipFileIndexCache;
private final File uninited = new File("U N I N I T E D");
@@ -164,8 +164,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
fsInfo = FSInfo.instance(context);
- useZipFileIndex = options.isSet("useOptimizedZip");
- if (useZipFileIndex)
+ contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true);
+ if (contextUseOptimizedZip)
zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
mmappedIO = options.isSet("mmappedIO");
@@ -471,9 +471,27 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
private static final RelativeDirectory symbolFilePrefix
= new RelativeDirectory("META-INF/sym/rt.jar/");
+ /*
+ * This method looks for a ZipFormatException and takes appropriate
+ * evasive action. If there is a failure in the fast mode then we
+ * fail over to the platform zip, and allow it to deal with a potentially
+ * non compliant zip file.
+ */
+ protected Archive openArchive(File zipFilename) throws IOException {
+ try {
+ return openArchive(zipFilename, contextUseOptimizedZip);
+ } catch (IOException ioe) {
+ if (ioe instanceof ZipFileIndex.ZipFormatException) {
+ return openArchive(zipFilename, false);
+ } else {
+ throw ioe;
+ }
+ }
+ }
+
/** Open a new zip file directory, and cache it.
*/
- protected Archive openArchive(File zipFileName) throws IOException {
+ private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException {
File origZipFileName = zipFileName;
if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) {
File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
@@ -495,7 +513,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
boolean usePreindexedCache = false;
String preindexCacheLocation = null;
- if (!useZipFileIndex) {
+ if (!useOptimizedZip) {
zdir = new ZipFile(zipFileName);
} else {
usePreindexedCache = options.isSet("usezipindex");
@@ -524,23 +542,22 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
}
if (origZipFileName == zipFileName) {
- if (!useZipFileIndex) {
+ if (!useOptimizedZip) {
archive = new ZipArchive(this, zdir);
} else {
archive = new ZipFileIndexArchive(this,
- zipFileIndexCache.getZipFileIndex(zipFileName,
+ zipFileIndexCache.getZipFileIndex(zipFileName,
null,
usePreindexedCache,
preindexCacheLocation,
options.isSet("writezipindexfiles")));
}
} else {
- if (!useZipFileIndex) {
+ if (!useOptimizedZip) {
archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix);
- }
- else {
+ } else {
archive = new ZipFileIndexArchive(this,
- zipFileIndexCache.getZipFileIndex(zipFileName,
+ zipFileIndexCache.getZipFileIndex(zipFileName,
symbolFilePrefix,
usePreindexedCache,
preindexCacheLocation,
@@ -549,6 +566,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
}
} catch (FileNotFoundException ex) {
archive = new MissingArchive(zipFileName);
+ } catch (ZipFileIndex.ZipFormatException zfe) {
+ throw zfe;
} catch (IOException ex) {
if (zipFileName.exists())
log.error("error.reading.file", zipFileName, getMessage(ex));
diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java
index fc9d1b3789f..1bee909914f 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java
@@ -492,10 +492,32 @@ public class ZipFileIndex {
public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
this.zipRandomFile = zipRandomFile;
this.zipFileIndex = index;
-
+ hasValidHeader();
findCENRecord(start, end);
}
+ /*
+ * the zip entry signature should be at offset 0, otherwise allow the
+ * calling logic to take evasive action by throwing ZipFormatException.
+ */
+ private boolean hasValidHeader() throws IOException {
+ final long pos = zipRandomFile.getFilePointer();
+ try {
+ if (zipRandomFile.read() == 'P') {
+ if (zipRandomFile.read() == 'K') {
+ if (zipRandomFile.read() == 0x03) {
+ if (zipRandomFile.read() == 0x04) {
+ return true;
+ }
+ }
+ }
+ }
+ } finally {
+ zipRandomFile.seek(pos);
+ }
+ throw new ZipFormatException("invalid zip magic");
+ }
+
/*
* Reads zip file central directory.
* For more details see readCEN in zip_util.c from the JDK sources.
@@ -529,7 +551,13 @@ public class ZipFileIndex {
zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12) + 2];
zipDir[0] = endbuf[i + 10];
zipDir[1] = endbuf[i + 11];
- zipRandomFile.seek(start + get4ByteLittleEndian(endbuf, i + 16));
+ int sz = get4ByteLittleEndian(endbuf, i + 16);
+ // a negative offset or the entries field indicates a
+ // potential zip64 archive
+ if (sz < 0 || get2ByteLittleEndian(zipDir, 0) == 0xffff) {
+ throw new ZipFormatException("detected a zip64 archive");
+ }
+ zipRandomFile.seek(start + sz);
zipRandomFile.readFully(zipDir, 2, zipDir.length - 2);
return;
} else {
@@ -1127,4 +1155,18 @@ public class ZipFileIndex {
}
}
+ /*
+ * Exception primarily used to implement a failover, used exclusively here.
+ */
+
+ static final class ZipFormatException extends IOException {
+ private static final long serialVersionUID = 8000196834066748623L;
+ protected ZipFormatException(String message) {
+ super(message);
+ }
+
+ protected ZipFormatException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
}
diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index d7107ad5626..fe1cb42db0b 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -638,6 +638,19 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
}
}
+ /** Resolve an identifier which may be the binary name of a class or
+ * the Java name of a class or package.
+ * @param name The name to resolve
+ */
+ public Symbol resolveBinaryNameOrIdent(String name) {
+ try {
+ Name flatname = names.fromString(name.replace("/", "."));
+ return reader.loadClass(flatname);
+ } catch (CompletionFailure ignore) {
+ return resolveIdent(name);
+ }
+ }
+
/** Resolve an identifier.
* @param name The identifier to resolve
*/
@@ -1058,7 +1071,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
} else {
boolean errors = false;
for (String nameStr : classnames) {
- Symbol sym = resolveIdent(nameStr);
+ Symbol sym = resolveBinaryNameOrIdent(nameStr);
if (sym == null || (sym.kind == Kinds.PCK && !processPcks)) {
log.error("proc.cant.find.class", nameStr);
errors = true;
@@ -1166,7 +1179,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
env.enclClass.sym.sourcefile :
env.toplevel.sourcefile);
try {
- attr.attribClass(env.tree.pos(), env.enclClass.sym);
+ attr.attrib(env);
if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
//if in fail-over mode, ensure that AST expression nodes
//are correctly initialized (e.g. they have a type/symbol)
diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
index 3af480c9385..5e34ee484fa 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -73,9 +73,14 @@ public class JavacTypes implements javax.lang.model.util.Types {
public Element asElement(TypeMirror t) {
Type type = cast(Type.class, t);
- if (type.tag != TypeTags.CLASS && type.tag != TypeTags.TYPEVAR)
- return null;
- return type.asElement();
+ switch (type.tag) {
+ case TypeTags.CLASS:
+ case TypeTags.ERROR:
+ case TypeTags.TYPEVAR:
+ return type.asElement();
+ default:
+ return null;
+ }
}
public boolean isSameType(TypeMirror t1, TypeMirror t2) {
diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index eee56d25725..e83c477b2af 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -820,13 +820,17 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** The set of package-info files to be processed this round. */
List packageInfoFiles;
+ /** The number of Messager errors generated in this round. */
+ int nMessagerErrors;
+
/** Create a round (common code). */
- private Round(Context context, int number, int priorWarnings) {
+ private Round(Context context, int number, int priorErrors, int priorWarnings) {
this.context = context;
this.number = number;
compiler = JavaCompiler.instance(context);
log = Log.instance(context);
+ log.nerrors = priorErrors;
log.nwarnings += priorWarnings;
log.deferDiagnostics = true;
@@ -840,7 +844,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** Create the first round. */
Round(Context context, List roots, List classSymbols) {
- this(context, 1, 0);
+ this(context, 1, 0, 0);
this.roots = roots;
genClassFiles = new HashMap();
@@ -860,7 +864,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** Create a new round. */
private Round(Round prev,
Set newSourceFiles, Map newClassFiles) {
- this(prev.nextContext(), prev.number+1, prev.compiler.log.nwarnings);
+ this(prev.nextContext(),
+ prev.number+1,
+ prev.nMessagerErrors,
+ prev.compiler.log.nwarnings);
this.genClassFiles = prev.genClassFiles;
List parsedFiles = compiler.parseFiles(newSourceFiles);
@@ -1014,6 +1021,8 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (taskListener != null)
taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
}
+
+ nMessagerErrors = messager.errorCount();
}
void showDiagnostics(boolean showAll) {
diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
index 4a3a5fa5bfb..889e2293bf3 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -1102,6 +1102,16 @@ compiler.warn.inexact.non-varargs.call=\
cast to {0} for a varargs call\n\
cast to {1} for a non-varargs call and to suppress this warning
+# 0: list of type
+compiler.warn.unreachable.catch=\
+ unreachable catch clause\n\
+ thrown type {0} has already been caught
+
+# 0: list of type
+compiler.warn.unreachable.catch.1=\
+ unreachable catch clause\n\
+ thrown types {0} have already been caught
+
# 0: symbol
compiler.warn.long.SVUID=\
serialVersionUID must be of type long in class {0}
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
index 033c385ef5d..cec4b954b4e 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -26,6 +26,7 @@
package com.sun.tools.javac.util;
import java.util.Collection;
+import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
@@ -226,17 +227,14 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
DiagnosticPart.SOURCE));
initFormat();
initIndentation();
+ if (options.isSet("oldDiags"))
+ initOldFormat();
String fmt = options.get("diagsFormat");
if (fmt != null) {
- String[] formats = fmt.split("\\|");
- switch (formats.length) {
- case 3:
- setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, formats[2]);
- case 2:
- setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, formats[1]);
- default:
- setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, formats[0]);
- }
+ if (fmt.equals("OLD"))
+ initOldFormat();
+ else
+ initFormats(fmt);
}
String srcPos = null;
if ((((srcPos = options.get("sourcePosition")) != null)) &&
@@ -280,14 +278,35 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
initFormat();
initIndentation();
}
- //where
+
private void initFormat() {
- availableFormats = new HashMap();
- setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, "%f:%l:%_%t%L%m");
- setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, "%p%L%m");
- setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, "%f:%_%t%L%m");
+ initFormats("%f:%l:%_%p%L%m", "%p%L%m", "%f:%_%p%L%m");
}
- //where
+
+ private void initOldFormat() {
+ initFormats("%f:%l:%_%t%L%m", "%p%L%m", "%f:%_%t%L%m");
+ }
+
+ private void initFormats(String pos, String nopos, String clazz) {
+ availableFormats = new EnumMap(BasicFormatKind.class);
+ setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, pos);
+ setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, nopos);
+ setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, clazz);
+ }
+
+ @SuppressWarnings("fallthrough")
+ private void initFormats(String fmt) {
+ String[] formats = fmt.split("\\|");
+ switch (formats.length) {
+ case 3:
+ setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, formats[2]);
+ case 2:
+ setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, formats[1]);
+ default:
+ setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, formats[0]);
+ }
+ }
+
private void initIndentation() {
indentationLevels = new HashMap();
setIndentation(DiagnosticPart.SUMMARY, 0);
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Options.java b/langtools/src/share/classes/com/sun/tools/javac/util/Options.java
index c44cfa960a1..1f68ddb1a35 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Options.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Options.java
@@ -75,6 +75,22 @@ public class Options {
return values.get(name.optionName);
}
+ /**
+ * Get the boolean value for an option, patterned after Boolean.getBoolean,
+ * essentially will return true, iff the value exists and is set to "true".
+ */
+ public boolean getBoolean(String name) {
+ return getBoolean(name, false);
+ }
+
+ /**
+ * Get the boolean with a default value if the option is not set.
+ */
+ public boolean getBoolean(String name, boolean defaultValue) {
+ String value = get(name);
+ return (value == null) ? defaultValue : Boolean.parseBoolean(value);
+ }
+
/**
* Check if the value for an undocumented option has been set.
*/
diff --git a/langtools/src/share/classes/javax/lang/model/element/Element.java b/langtools/src/share/classes/javax/lang/model/element/Element.java
index 522faa6405b..f46c2cf26f5 100644
--- a/langtools/src/share/classes/javax/lang/model/element/Element.java
+++ b/langtools/src/share/classes/javax/lang/model/element/Element.java
@@ -197,11 +197,12 @@ public interface Element {
* If this is a {@linkplain
* PackageElement#getEnclosingElement package}, {@code null} is
* returned.
-
+ *
* If this is a {@linkplain
* TypeParameterElement#getEnclosingElement type parameter},
- * {@code null} is returned.
-
+ * {@linkplain TypeParameterElement#getGenericElement the
+ * generic element} of the type parameter is returned.
+ *
*
*
* @return the enclosing element, or {@code null} if there is none
diff --git a/langtools/src/share/classes/javax/lang/model/element/TypeParameterElement.java b/langtools/src/share/classes/javax/lang/model/element/TypeParameterElement.java
index e6a0536bc5a..f9b128e2490 100644
--- a/langtools/src/share/classes/javax/lang/model/element/TypeParameterElement.java
+++ b/langtools/src/share/classes/javax/lang/model/element/TypeParameterElement.java
@@ -64,9 +64,9 @@ public interface TypeParameterElement extends Element {
List extends TypeMirror> getBounds();
/**
- * Returns {@code null}.
+ * Returns the {@linkplain TypeParameterElement#getGenericElement generic element} of this type parameter.
*
- * @return {@code null}
+ * @return the generic element of this type parameter
*/
@Override
Element getEnclosingElement();
diff --git a/langtools/test/com/sun/javadoc/testUseOption/C.java b/langtools/test/com/sun/javadoc/testUseOption/C.java
new file mode 100644
index 00000000000..419d36ba73c
--- /dev/null
+++ b/langtools/test/com/sun/javadoc/testUseOption/C.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/**
+ * Class in an unnamed package.
+ */
+
+public class C {
+
+ /**
+ * Field in C.
+ */
+ public UsedInC fieldInC;
+
+ /**
+ * Method in C.
+ */
+ public UsedInC methodInC(UsedInC p) {
+ return p;
+ }
+}
diff --git a/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java b/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java
index f03f24002bc..58f56073a38 100644
--- a/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java
+++ b/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4496290 4985072
+ * @bug 4496290 4985072 7006178
* @summary A simple test to determine if -use works.
* @author jamieh
* @library ../lib/
@@ -34,7 +34,7 @@
public class TestUseOption extends JavadocTester {
- private static final String BUG_ID = "4496290-4985072";
+ private static final String BUG_ID = "4496290-4985072-7006178";
//Input for string search tests.
private static final String[] TEST2 = {
@@ -54,6 +54,16 @@ public class TestUseOption extends JavadocTester {
"Method in C8.",
};
+ private static final String[][] TEST3 = {
+ {BUG_ID + "-3" + FS + "class-use" + FS + "UsedInC.html", "Uses of " +
+ "UsedInC in <Unnamed> "
+ },
+ {BUG_ID + "-3" + FS + "package-use.html", "" +
+ "UsedInC "
+ }
+ };
+
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
};
@@ -62,6 +72,10 @@ public class TestUseOption extends JavadocTester {
"-d", BUG_ID+"-2", "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
};
+ private static final String[] ARGS3 = new String[] {
+ "-d", BUG_ID + "-3", "-sourcepath", SRC_DIR, "-use", SRC_DIR + FS + "C.java", SRC_DIR + FS + "UsedInC.java"
+ };
+
/**
* The entry point of the test.
* @param args the array of command line arguments.
@@ -93,6 +107,8 @@ public class TestUseOption extends JavadocTester {
prevIndex = currentIndex;
}
tester.printSummary();
+ run(tester, ARGS3, TEST3, NO_TEST);
+ tester.printSummary();
}
/**
diff --git a/langtools/test/com/sun/javadoc/testUseOption/UsedInC.java b/langtools/test/com/sun/javadoc/testUseOption/UsedInC.java
new file mode 100644
index 00000000000..61b43eda51d
--- /dev/null
+++ b/langtools/test/com/sun/javadoc/testUseOption/UsedInC.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+public class UsedInC
+{
+}
diff --git a/langtools/test/tools/apt/Compile/golden.txt b/langtools/test/tools/apt/Compile/golden.txt
index 42ee8bd867b..180efe276d2 100644
--- a/langtools/test/tools/apt/Compile/golden.txt
+++ b/langtools/test/tools/apt/Compile/golden.txt
@@ -1,6 +1,6 @@
error: It's a mad, mad, mad, mad world
error: Something wicked this way comes
-HelloWorld.java:2: Boring class name
+HelloWorld.java:2: error: Boring class name
public class HelloWorld {
^
3 errors
diff --git a/langtools/test/tools/javac/4846262/Test.out b/langtools/test/tools/javac/4846262/Test.out
index 254d9d2f644..175101fa83a 100644
--- a/langtools/test/tools/javac/4846262/Test.out
+++ b/langtools/test/tools/javac/4846262/Test.out
@@ -1,7 +1,7 @@
-Test.java:4: not a statement
+Test.java:4: error: not a statement
abcdefg
^
-Test.java:4: ';' expected
+Test.java:4: error: ';' expected
abcdefg
^
2 errors
diff --git a/langtools/test/tools/javac/6508981/TestInferBinaryName.java b/langtools/test/tools/javac/6508981/TestInferBinaryName.java
index aeb91cfebba..b14bdc01894 100644
--- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java
+++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java
@@ -139,9 +139,8 @@ public class TestInferBinaryName {
throws IOException {
Context ctx = new Context();
Options options = Options.instance(ctx);
- // uugh, ugly back door, should be cleaned up, someday
- if (zipFileIndexKind == USE_ZIP_FILE_INDEX)
- options.put("useOptimizedZip", "true");
+ options.put("useOptimizedZip",
+ Boolean.toString(zipFileIndexKind == USE_ZIP_FILE_INDEX));
if (symFileKind == IGNORE_SYMBOL_FILE)
options.put("ignore.symbol.file", "true");
diff --git a/langtools/test/tools/javac/6558548/T6558548.java b/langtools/test/tools/javac/6558548/T6558548.java
new file mode 100644
index 00000000000..09bbda66237
--- /dev/null
+++ b/langtools/test/tools/javac/6558548/T6558548.java
@@ -0,0 +1,300 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6558548
+ * @summary The compiler needs to be aligned with clarified specification of throws
+ * @compile/fail/ref=T6558548_latest.out -XDrawDiagnostics T6558548.java
+ * @compile/fail/ref=T6558548_6.out -source 6 -XDrawDiagnostics T6558548.java
+ */
+
+class T6558548 {
+
+ void nothing() {}
+ void checked() throws InterruptedException {}
+ void runtime() throws IllegalArgumentException {}
+
+ void m1() {
+ try {
+ throw new java.io.FileNotFoundException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m1a() {
+ try {
+ throw new java.io.IOException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } //ok
+ }
+
+ void m2() {
+ try {
+ nothing();
+ }
+ catch(Exception exc) { } // ok
+ }
+
+ void m3() {
+ try {
+ checked();
+ }
+ catch(Exception exc) { } //ok
+ }
+
+ void m4() {
+ try {
+ runtime();
+ }
+ catch(Exception exc) { } //ok
+ }
+
+ void m5() {
+ try {
+ nothing();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m6() {
+ try {
+ checked();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m7() {
+ try {
+ runtime();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m9() {
+ try {
+ checked();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m10() {
+ try {
+ runtime();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m11() {
+ try {
+ nothing();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m12() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m13() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m14() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m15() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //ok
+ }
+
+ void m16() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m17() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m18() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m19() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m20() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m21() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // ok
+ }
+
+ void m22() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m23() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m24() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m25() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m26() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m27() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m28() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m29() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m30() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m31() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m32() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m33() {
+ try {
+ checked();
+ }
+ catch(InterruptedException exc) { } //ok
+ }
+
+ void m34() {
+ try {
+ runtime();
+ }
+ catch(InterruptedException exc) { } //never thrown in try
+ }
+
+ void m35() {
+ try {
+ nothing();
+ }
+ catch(InterruptedException exc) { } //never thrown in try
+ }
+}
diff --git a/langtools/test/tools/javac/6558548/T6558548_6.out b/langtools/test/tools/javac/6558548/T6558548_6.out
new file mode 100644
index 00000000000..551ed33e503
--- /dev/null
+++ b/langtools/test/tools/javac/6558548/T6558548_6.out
@@ -0,0 +1,9 @@
+- compiler.warn.source.no.bootclasspath: 1.6
+T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+6 errors
+1 warning
diff --git a/langtools/test/tools/javac/6558548/T6558548_latest.out b/langtools/test/tools/javac/6558548/T6558548_latest.out
new file mode 100644
index 00000000000..ee686cb4a6a
--- /dev/null
+++ b/langtools/test/tools/javac/6558548/T6558548_latest.out
@@ -0,0 +1,23 @@
+T6558548.java:20:9: compiler.warn.unreachable.catch: java.io.FileNotFoundException
+T6558548.java:134:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:142:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:151:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException
+T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:160:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:169:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:185:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:193:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:211:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:220:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:230:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException,java.lang.Error
+T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:240:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:250:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:268:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:277:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+6 errors
+15 warnings
diff --git a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
index 84d096a4ff1..922b00fcebd 100644
--- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
+++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, 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
@@ -261,7 +261,7 @@ public class T6769027 {
enum PositionKind {
NOPOS(Position.NOPOS, "- ", "error: "),
- POS(5, "Test.java:1:6: ", "/Test.java:1: ");
+ POS(5, "Test.java:1:6: ", "/Test.java:1: error: ");
int pos;
String rawOutput;
diff --git a/langtools/test/tools/javac/Diagnostics/7010608/Test.java b/langtools/test/tools/javac/Diagnostics/7010608/Test.java
new file mode 100644
index 00000000000..d0b718ddebc
--- /dev/null
+++ b/langtools/test/tools/javac/Diagnostics/7010608/Test.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 7010608
+ * @summary the string 'error' should appear in error messages
+ */
+
+import java.io.*;
+import java.net.URI;
+import java.util.*;
+import javax.tools.*;
+import javax.tools.JavaCompiler.CompilationTask;
+
+public class Test {
+ public static void main(String... args) throws Exception {
+ new Test().run();
+ }
+
+ void run() throws Exception {
+ Locale prev = Locale.getDefault();
+ Locale.setDefault(Locale.ENGLISH);
+ try {
+ test(Arrays.asList(),
+ "myfo://test:1: error: cannot find symbol");
+ test(Arrays.asList("-XDdiagsFormat=OLD"),
+ "myfo://test:1: cannot find symbol");
+ test(Arrays.asList("-XDoldDiags"),
+ "myfo://test:1: cannot find symbol");
+ } finally {
+ Locale.setDefault(prev);
+ }
+ }
+
+ void test(List options, String expect) throws Exception {
+ System.err.println("test: " + options);
+ JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ JavaFileObject f = new MyFileObject("myfo://test", "class Bad { Missing x; }");
+ List extends JavaFileObject> files = Arrays.asList(f);
+ CompilationTask task = javac.getTask(pw, null, null, options, null, files);
+ boolean ok = task.call();
+ pw.close();
+ String out = sw.toString();
+ if (!out.isEmpty())
+ System.err.println(out);
+ if (ok)
+ throw new Exception("Compilation succeeded unexpectedly");
+ if (!out.contains(expect))
+ throw new Exception("expected text not found: " + expect);
+ }
+
+ class MyFileObject extends SimpleJavaFileObject {
+ MyFileObject(String uri, String text) {
+ super(URI.create(uri), JavaFileObject.Kind.SOURCE);
+ this.text = text;
+ }
+ @Override
+ public String getName() {
+ return uri.toString();
+ }
+ @Override
+ public String getCharContent(boolean ignoreEncodingErrors) {
+ return text;
+ }
+ final String text;
+ }
+}
+
+
diff --git a/langtools/test/tools/javac/annotations/TestAnnotationPackageInfo.java b/langtools/test/tools/javac/annotations/TestAnnotationPackageInfo.java
new file mode 100644
index 00000000000..ac7593c3d49
--- /dev/null
+++ b/langtools/test/tools/javac/annotations/TestAnnotationPackageInfo.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6993311
+ * @summary annotations on packages are not validated
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.tools.*;
+import com.sun.source.util.*;
+
+public class TestAnnotationPackageInfo {
+ public static void main(String... args) throws Exception {
+ new TestAnnotationPackageInfo().run();
+ }
+
+ static class MyFileObject extends SimpleJavaFileObject {
+ private String text;
+ public MyFileObject(String fileName, String text) {
+ super(URI.create("myfo:/" + fileName), JavaFileObject.Kind.SOURCE);
+ this.text = text;
+ }
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return text;
+ }
+ }
+
+ public void run() throws Exception {
+ final String bootPath = System.getProperty("sun.boot.class.path");
+ final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+ assert tool != null;
+
+ JavaFileObject test_java = new MyFileObject("test/Test.java",
+ "package test; public @interface Test {\n" +
+ " public int mandatory();\n" +
+ "}\n");
+
+ JavaFileObject package_info_java = new MyFileObject("test/package-info.java",
+ "@Test package test;");
+
+ DiagnosticCollector coll = new DiagnosticCollector();
+
+ List options = Arrays.asList("-bootclasspath", bootPath);
+ List extends JavaFileObject> files = Arrays.asList(test_java, package_info_java);
+ JavacTask ct = (JavacTask)tool.getTask(null, null, coll, options, null, files);
+ ct.analyze();
+
+ String expectedCode = "compiler.err.annotation.missing.default.value";
+ List> diags = coll.getDiagnostics();
+ switch (diags.size()) {
+ case 0:
+ throw new Exception("no diagnostics reported");
+ case 1:
+ String code = diags.get(0).getCode();
+ if (code.equals(expectedCode))
+ return;
+ throw new Exception("unexpected diag: " + diags.get(0));
+ default:
+ throw new Exception("unexpected diags reported: " + diags);
+ }
+ }
+}
diff --git a/langtools/test/tools/javac/annotations/pos/package-info.java b/langtools/test/tools/javac/annotations/pos/package-info.java
index dc18796ac39..460a0fcb7d9 100644
--- a/langtools/test/tools/javac/annotations/pos/package-info.java
+++ b/langtools/test/tools/javac/annotations/pos/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, 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
@@ -23,12 +23,12 @@
/*
* @test
- * @bug 4901290
+ * @bug 4901290 6993311
* @summary Package annotations
* @author gafter
*
* @compile package-info.java
*/
-@java.lang.annotation.Documented
+@Deprecated
package foo.bar;
diff --git a/langtools/test/tools/javac/api/6411310/Test.java b/langtools/test/tools/javac/api/6411310/Test.java
index b7702d705a6..aec6c7db615 100644
--- a/langtools/test/tools/javac/api/6411310/Test.java
+++ b/langtools/test/tools/javac/api/6411310/Test.java
@@ -153,14 +153,12 @@ public class Test {
Context c = new Context();
Options options = Options.instance(c);
- if (useOptimizedZip) {
- options.put("useOptimizedZip", "true");
- }
+ options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
- if (!useSymbolFile) {
- options.put("ignore.symbol.file", "true");
- }
- return new JavacFileManager(c, false, null);
+ if (!useSymbolFile) {
+ options.put("ignore.symbol.file", "true");
+ }
+ return new JavacFileManager(c, false, null);
}
File createDir(String name, String... entries) throws Exception {
diff --git a/langtools/test/tools/javac/api/6557752/T6557752.java b/langtools/test/tools/javac/api/6557752/T6557752.java
index c920a953e6e..fe748bee53e 100644
--- a/langtools/test/tools/javac/api/6557752/T6557752.java
+++ b/langtools/test/tools/javac/api/6557752/T6557752.java
@@ -118,7 +118,8 @@ public class T6557752 {
Types types = task.getTypes();
- if (types.asElement(trees.getOriginalType((ErrorType)typeMirror)) != null) {
+ str1 = types.asElement(trees.getOriginalType((ErrorType)typeMirror)).toString();
+ if (!str1.equals("FooBar")) {
throw new AssertionError("Types.asElement() error!");
}
foundError = true;
diff --git a/langtools/test/tools/javac/api/T6838467.java b/langtools/test/tools/javac/api/T6838467.java
index daa5a654a76..b08412d6f79 100644
--- a/langtools/test/tools/javac/api/T6838467.java
+++ b/langtools/test/tools/javac/api/T6838467.java
@@ -178,12 +178,10 @@ public class T6838467 {
return fm;
}
- JavacFileManager createFileManager(boolean useOptimedZipIndex) {
+ JavacFileManager createFileManager(boolean useOptimizedZip) {
Context ctx = new Context();
- if (useOptimedZipIndex) {
- Options options = Options.instance(ctx);
- options.put("useOptimizedZip", "true");
- }
+ Options options = Options.instance(ctx);
+ options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
return new JavacFileManager(ctx, false, null);
}
diff --git a/langtools/test/tools/javac/api/T6877206.java b/langtools/test/tools/javac/api/T6877206.java
index 5a8442ad22a..3c82bb3e500 100644
--- a/langtools/test/tools/javac/api/T6877206.java
+++ b/langtools/test/tools/javac/api/T6877206.java
@@ -168,9 +168,7 @@ public class T6877206 {
JavacFileManager createFileManager(boolean useOptimizedZip, boolean useSymbolFile) {
Context ctx = new Context();
Options options = Options.instance(ctx);
- if (useOptimizedZip) {
- options.put("useOptimizedZip", "true");
- }
+ options.put("useOptimizedZip", Boolean.toString(useOptimizedZip));
if (!useSymbolFile) {
options.put("ignore.symbol.file", "true");
}
diff --git a/langtools/test/tools/javac/api/TestJavacTask_Lock.java b/langtools/test/tools/javac/api/TestJavacTask_Lock.java
new file mode 100644
index 00000000000..cc27c11765b
--- /dev/null
+++ b/langtools/test/tools/javac/api/TestJavacTask_Lock.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/*
+ * @test
+ * @bug 7026509
+ * @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import javax.tools.JavaCompiler.CompilationTask;
+import com.sun.source.util.*;
+
+public class TestJavacTask_Lock {
+ public static void main(String... args) throws Exception {
+ new TestJavacTask_Lock().run();
+ }
+
+ enum MethodKind {
+ CALL {
+ int test(CompilationTask t) {
+ boolean ok = t.call();
+ if (!ok)
+ throw new Error("compilation failed");
+ return 1;
+ }
+ },
+ PARSE {
+ int test(CompilationTask t) {
+ try {
+ ((JavacTask) t).parse();
+ return 1;
+ } catch (IOException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ };
+ abstract int test(CompilationTask t);
+ }
+
+ JavaCompiler comp;
+ StandardJavaFileManager fm;
+
+ void run() throws Exception {
+ comp = ToolProvider.getSystemJavaCompiler();
+ fm = comp.getStandardFileManager(null, null, null);
+
+ for (MethodKind first: MethodKind.values()) {
+ for (MethodKind second: MethodKind.values()) {
+ test(first, second);
+ }
+ }
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ void test(MethodKind first, MethodKind second) {
+ System.err.println("test: " + first + ", " + second);
+ File testSrc = new File(System.getProperty("test.src"));
+ String thisClassName = TestJavacTask_Lock.class.getName();
+ Iterable extends JavaFileObject> files =
+ fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
+ File tmpDir = new File(first + "_" + second);
+ tmpDir.mkdirs();
+ List options = Arrays.asList( "-d", tmpDir.getPath() );
+ CompilationTask t = comp.getTask(null, fm, null, options, null, files);
+
+ try {
+ first.test(t);
+ second.test(t);
+ error("No exception thrown");
+ } catch (IllegalStateException e) {
+ System.err.println("Expected exception caught: " + e);
+ } catch (Exception e) {
+ error("Unexpected exception caught: " + e);
+ e.printStackTrace(System.err);
+ }
+
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int errors;
+}
diff --git a/langtools/test/tools/javac/api/TestJavacTask_Multiple.java b/langtools/test/tools/javac/api/TestJavacTask_Multiple.java
new file mode 100644
index 00000000000..c80cc6e00cf
--- /dev/null
+++ b/langtools/test/tools/javac/api/TestJavacTask_Multiple.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/*
+ * @test
+ * @bug 7026509
+ * @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.tools.*;
+import javax.tools.JavaCompiler.CompilationTask;
+import com.sun.source.util.*;
+
+public class TestJavacTask_Multiple {
+ public static void main(String... args) throws Exception {
+ new TestJavacTask_Multiple().run();
+ }
+
+ final int MAX_TASKS = 3;
+
+ enum TestKind {
+ CALL {
+ int test(CompilationTask t) {
+ boolean ok = t.call();
+ if (!ok)
+ throw new Error("compilation failed");
+ return 1;
+ }
+ },
+ PARSE {
+ int test(CompilationTask t) {
+ try {
+ ((JavacTask) t).parse();
+ return 1;
+ } catch (IOException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ };
+ abstract int test(CompilationTask t);
+ }
+
+ int count;
+
+ void run() throws Exception {
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+ for (TestKind tk: TestKind.values()) {
+ test(comp, fm, tk);
+ }
+
+ int expect = TestKind.values().length * MAX_TASKS;
+ if (count != expect) {
+ throw new Exception("Unexpected number of tests completed: " + count
+ + ", expected: " + expect);
+ }
+
+ }
+
+ void test(JavaCompiler comp, StandardJavaFileManager fm, TestKind tk) {
+ System.err.println("test " + tk);
+ File testSrc = new File(System.getProperty("test.src"));
+ String thisClassName = TestJavacTask_Multiple.class.getName();
+ Iterable extends JavaFileObject> files =
+ fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
+
+ List tasks = new ArrayList();
+ for (int i = 1; i <= MAX_TASKS; i++) {
+ File tmpDir = new File(tk + "_" + i);
+ tmpDir.mkdirs();
+ List options = Arrays.asList( "-d", tmpDir.getPath() );
+ CompilationTask t = comp.getTask(null, fm, null, options, null, files);
+ ((JavacTask) t).setTaskListener(createTaskListener(tk, i));
+ tasks.add(t);
+ }
+
+ for (CompilationTask t: tasks)
+ count += tk.test(t);
+
+ System.err.println();
+ }
+
+ TaskListener createTaskListener(final TestKind tk, final int i) {
+ return new TaskListener() {
+
+ public void started(TaskEvent e) {
+ System.err.println(tk + "." + i + ": " + e + " started");
+ }
+
+ public void finished(TaskEvent e) {
+ System.err.println(tk + "." + i + ": " + e + " finished");
+ }
+ };
+ }
+}
diff --git a/langtools/test/tools/javac/api/TestJavacTask_ParseAttrGen.java b/langtools/test/tools/javac/api/TestJavacTask_ParseAttrGen.java
new file mode 100644
index 00000000000..e318b3e0a58
--- /dev/null
+++ b/langtools/test/tools/javac/api/TestJavacTask_ParseAttrGen.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/*
+ * @test
+ * @bug 7026509
+ * @summary Cannot use JavaCompiler to create multiple CompilationTasks for partial compilations
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+
+public class TestJavacTask_ParseAttrGen {
+ public static void main(String... args) throws Exception {
+ new TestJavacTask_ParseAttrGen().run();
+ }
+
+ JavaCompiler comp;
+ StandardJavaFileManager fm;
+
+ void run() throws Exception {
+ comp = ToolProvider.getSystemJavaCompiler();
+ fm = comp.getStandardFileManager(null, null, null);
+
+ final boolean[] booleanValues = { false, true };
+ for (boolean pk: booleanValues) {
+ for (boolean ak: booleanValues) {
+ for (boolean gk: booleanValues) {
+ test(pk, ak, gk);
+ }
+ }
+ }
+ }
+
+ void test(boolean pk, boolean ak, boolean gk) throws Exception {
+ if (!pk && !ak && !gk) // nothing to do
+ return;
+
+ System.err.println("test: pk:" + pk + ", ak:" + ak + ", gk: " + gk);
+ File testSrc = new File(System.getProperty("test.src"));
+ String thisClassName = TestJavacTask_ParseAttrGen.class.getName();
+ Iterable extends JavaFileObject> files =
+ fm.getJavaFileObjects(new File(testSrc, thisClassName + ".java"));
+ File tmpDir = new File((pk ? "p" : "") + (ak ? "a" : "") + (gk ? "g" : ""));
+ tmpDir.mkdirs();
+ fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tmpDir));
+ JavacTask t = (JavacTask) comp.getTask(null, fm, null, null, null, files);
+ //t.setTaskListener(createTaskListener());
+
+ try {
+ if (pk) {
+ Iterable extends CompilationUnitTree> trees = t.parse();
+ System.err.println(count(trees) + " trees parsed");
+ }
+
+ if (ak) {
+ Iterable extends Element> elems = t.analyze();
+ System.err.println(count(elems) + " elements analyzed");
+ }
+
+ if (gk) {
+ Iterable extends JavaFileObject> classfiles = t.generate();
+ System.err.println(count(classfiles) + " class files generated");
+ }
+ } catch (IOException e) {
+ error("unexpected exception caught: " + e);
+ }
+
+ File[] genFiles = tmpDir.listFiles();
+ int expect = (gk ? 2 : 0); // main class and anon class for TaskListener
+ if (genFiles.length != expect)
+ error("unexpected number of files generated: " + genFiles.length
+ + ", expected: " + expect);
+
+ System.err.println();
+ }
+
+ TaskListener createTaskListener() {
+ return new TaskListener() {
+ public void started(TaskEvent e) {
+ System.err.println(e + " started");
+ }
+
+ public void finished(TaskEvent e) {
+ System.err.println(e + " finished");
+ }
+ };
+ }
+
+ int count(Iterable items) {
+ int count = 0;
+ for (T item: items)
+ count++;
+ return count;
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int errors;
+}
diff --git a/langtools/test/tools/javac/diags/examples/CountError.java b/langtools/test/tools/javac/diags/examples/CountError.java
index 782d45d9241..2d09842c12a 100644
--- a/langtools/test/tools/javac/diags/examples/CountError.java
+++ b/langtools/test/tools/javac/diags/examples/CountError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -23,6 +23,7 @@
// key: compiler.misc.count.error
// key: compiler.err.unreported.exception.need.to.catch.or.throw
+// key: compiler.err.error
// run: backdoor
class CountError {
diff --git a/langtools/test/tools/javac/diags/examples/CountErrorPlural.java b/langtools/test/tools/javac/diags/examples/CountErrorPlural.java
index efd8dc4255b..9d5ecb98c80 100644
--- a/langtools/test/tools/javac/diags/examples/CountErrorPlural.java
+++ b/langtools/test/tools/javac/diags/examples/CountErrorPlural.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -23,6 +23,7 @@
// key: compiler.misc.count.error.plural
// key: compiler.err.unreported.exception.need.to.catch.or.throw
+// key: compiler.err.error
// run: backdoor
class CountErrorPlural {
diff --git a/langtools/test/tools/javac/diags/examples/IdentifierExpected.java b/langtools/test/tools/javac/diags/examples/IdentifierExpected.java
index 440b2688dd8..f36b8ad2161 100644
--- a/langtools/test/tools/javac/diags/examples/IdentifierExpected.java
+++ b/langtools/test/tools/javac/diags/examples/IdentifierExpected.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -25,6 +25,7 @@
// key: compiler.err.expected
// key: compiler.err.invalid.binary.number
// key: compiler.misc.count.error.plural
+// key: compiler.err.error
// run: backdoor
class IdentifierExpected {
diff --git a/langtools/test/tools/javac/diags/examples/KindnameClass.java b/langtools/test/tools/javac/diags/examples/KindnameClass.java
index 245e75332c3..4f856607cc4 100644
--- a/langtools/test/tools/javac/diags/examples/KindnameClass.java
+++ b/langtools/test/tools/javac/diags/examples/KindnameClass.java
@@ -25,6 +25,7 @@
// key: compiler.err.cant.resolve.location
// key: compiler.misc.location
// key: compiler.misc.count.error
+// key: compiler.err.error
// run: backdoor
class KindnameClass {
diff --git a/langtools/test/tools/javac/diags/examples/KindnameConstructor.java b/langtools/test/tools/javac/diags/examples/KindnameConstructor.java
index c451c3a3ad9..21396b58b98 100644
--- a/langtools/test/tools/javac/diags/examples/KindnameConstructor.java
+++ b/langtools/test/tools/javac/diags/examples/KindnameConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -28,6 +28,7 @@
// key: compiler.misc.arg.length.mismatch
// key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.count.error.plural
+// key: compiler.err.error
// run: backdoor
class KindnameConstructor {
diff --git a/langtools/test/tools/javac/diags/examples/KindnameMethod.java b/langtools/test/tools/javac/diags/examples/KindnameMethod.java
index 3bcb7605585..7dd283fe4ca 100644
--- a/langtools/test/tools/javac/diags/examples/KindnameMethod.java
+++ b/langtools/test/tools/javac/diags/examples/KindnameMethod.java
@@ -26,6 +26,7 @@
// key: compiler.err.cant.resolve.location.args
// key: compiler.misc.location
// key: compiler.misc.count.error
+// key: compiler.err.error
// run: backdoor
class KindnameMethod {
diff --git a/langtools/test/tools/javac/diags/examples/KindnameVariable.java b/langtools/test/tools/javac/diags/examples/KindnameVariable.java
index 894322b1a48..e88f30f7aa0 100644
--- a/langtools/test/tools/javac/diags/examples/KindnameVariable.java
+++ b/langtools/test/tools/javac/diags/examples/KindnameVariable.java
@@ -26,6 +26,7 @@
// key: compiler.err.cant.resolve.location
// key: compiler.misc.location
// key: compiler.misc.count.error
+// key: compiler.err.error
// run: backdoor
class KindnameVariable {
diff --git a/langtools/test/tools/javac/diags/examples/UnreachableCatch.java b/langtools/test/tools/javac/diags/examples/UnreachableCatch.java
new file mode 100644
index 00000000000..5189e7a2757
--- /dev/null
+++ b/langtools/test/tools/javac/diags/examples/UnreachableCatch.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+// key: compiler.warn.unreachable.catch
+
+class UnreachableCatch {
+
+ void test() {
+ try {
+ throw new java.io.FileNotFoundException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } //unreachable
+ }
+}
diff --git a/langtools/test/tools/javac/diags/examples/UnreachableCatch1.java b/langtools/test/tools/javac/diags/examples/UnreachableCatch1.java
new file mode 100644
index 00000000000..3cf6ac32c7b
--- /dev/null
+++ b/langtools/test/tools/javac/diags/examples/UnreachableCatch1.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+// key: compiler.warn.unreachable.catch.1
+
+class UnreachableCatch1 {
+
+ void test() {
+ try {
+ throw new IllegalArgumentException();
+ }
+ catch(Error err) { }
+ catch(RuntimeException rex) { }
+ catch(Throwable t) { } //unreachable
+ }
+}
diff --git a/langtools/test/tools/javac/file/zip/T6836682.java b/langtools/test/tools/javac/file/zip/T6836682.java
new file mode 100644
index 00000000000..c25779b6112
--- /dev/null
+++ b/langtools/test/tools/javac/file/zip/T6836682.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6836682 7025988
+ * @summary JavacFileManager handling of zip64 archives (Scenario A and B)
+ * @compile -XDignore.symbol.file T6836682.java Utils.java
+ * @run main T6836682
+ */
+/*
+ * This test consists of two scenarios:
+ *
+ * Scenario A: create a jar with entries exceeding 64K, and see if the javac
+ * can handle this large jar on the classpath. Generally this test completes
+ * within a minute
+ *
+ * Scenario B: create a jar with a large enough file exceeding 4GB, and
+ * similarly test javac. This test is known to be slow and problematic on
+ * certain operating systems, thus this test can be selected by passing a
+ * property through jtreg as follows:
+ * -javaoptions=-DT6836682.testScenarioB=true.
+ * Note this test will only run iff all the disk requirements are met at runtime.
+ */
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class T6836682 {
+
+ private static final long GIGA = 1024 * 1024 * 1024;
+ private static final int BUFFER_LEN = Short.MAX_VALUE * 2;
+
+ static long getCount(long minlength) {
+ return (minlength / BUFFER_LEN) + 1;
+ }
+
+ static long computeCRC(long minlength) {
+ CRC32 crc = new CRC32();
+ byte[] buffer = new byte[BUFFER_LEN];
+ long count = getCount(minlength);
+ for (long i = 0; i < count; i++) {
+ crc.update(buffer);
+ }
+ return crc.getValue();
+ }
+
+ static long computeCRC(File inFile) throws IOException {
+ byte[] buffer = new byte[8192];
+ CRC32 crc = new CRC32();
+ FileInputStream fis = null;
+ BufferedInputStream bis = null;
+ try {
+ fis = new FileInputStream(inFile);
+ bis = new BufferedInputStream(fis);
+ int n = bis.read(buffer);
+ while (n > 0) {
+ crc.update(buffer, 0, n);
+ n = bis.read(buffer);
+ }
+ } finally {
+ Utils.close(bis);
+ Utils.close(fis);
+ }
+ return crc.getValue();
+ }
+
+ static void createLargeFile(OutputStream os, long minlength) throws IOException {
+ byte[] buffer = new byte[BUFFER_LEN];
+ long count = getCount(minlength);
+ for (long i = 0; i < count; i++) {
+ os.write(buffer);
+ }
+ os.flush();
+ }
+
+ static void createJarWithLargeFile(File jarFile, File javaFile,
+ long minlength) throws IOException {
+ Utils.createClassFile(javaFile, null, true);
+ File classFile = new File(Utils.getClassFileName(javaFile));
+ ZipOutputStream zos = null;
+ BufferedOutputStream bos = null;
+ FileInputStream fis = null;
+ try {
+ zos = new ZipOutputStream(new FileOutputStream(jarFile));
+ zos.setLevel(ZipOutputStream.STORED);
+ zos.setMethod(0);
+ bos = new BufferedOutputStream(zos);
+
+ ZipEntry ze = new ZipEntry("large.data");
+ ze.setCompressedSize(getCount(minlength) * BUFFER_LEN);
+ ze.setSize(getCount(minlength) * BUFFER_LEN);
+ ze.setCrc(computeCRC(minlength));
+ ze.setMethod(ZipEntry.STORED);
+ zos.putNextEntry(ze);
+ createLargeFile(bos, minlength);
+
+ ze = new ZipEntry(classFile.getName());
+ ze.setCompressedSize(classFile.length());
+ ze.setSize(classFile.length());
+ ze.setCrc(computeCRC(classFile));
+ ze.setMethod(ZipEntry.STORED);
+ zos.putNextEntry(ze);
+ fis = new FileInputStream(classFile);
+ Utils.copyStream(fis, bos);
+ bos.flush();
+ zos.closeEntry();
+ } finally {
+ Utils.close(bos);
+ Utils.close(zos);
+ Utils.close(fis);
+ }
+ // deleted to prevent accidental linkage
+ new File(Utils.getClassFileName(javaFile)).delete();
+ }
+
+ static void createLargeJar(File jarFile, File javaFile) throws IOException {
+ File classFile = new File(Utils.getClassFileName(javaFile));
+ Utils.createClassFile(javaFile, null, true);
+ ZipOutputStream zos = null;
+ FileInputStream fis = null;
+ final int MAX = Short.MAX_VALUE * 2 + 10;
+ ZipEntry ze = null;
+ try {
+ zos = new ZipOutputStream(new FileOutputStream(jarFile));
+ zos.setLevel(ZipOutputStream.STORED);
+ zos.setMethod(ZipOutputStream.STORED);
+ for (int i = 0; i < MAX ; i++) {
+ ze = new ZipEntry("X" + i + ".txt");
+ ze.setSize(0);
+ ze.setCompressedSize(0);
+ ze.setCrc(0);
+ zos.putNextEntry(ze);
+ }
+
+ // add a class file
+ ze = new ZipEntry(classFile.getName());
+ ze.setCompressedSize(classFile.length());
+ ze.setSize(classFile.length());
+ ze.setCrc(computeCRC(classFile));
+ zos.putNextEntry(ze);
+ fis = new FileInputStream(classFile);
+ Utils.copyStream(fis, zos);
+ } finally {
+ Utils.close(zos);
+ Utils.close(fis);
+ // deleted to prevent accidental linkage
+ new File(Utils.getClassFileName(javaFile)).delete();
+ }
+ }
+
+ // a jar with entries exceeding 64k + a class file for the existential test
+ public static void testScenarioA(String... args) throws IOException {
+ File largeJar = new File("large.jar");
+ File javaFile = new File("Foo.java");
+ createLargeJar(largeJar, javaFile);
+
+ File testFile = new File("Bar.java");
+ try {
+ Utils.createJavaFile(testFile, javaFile);
+ if (!Utils.compile("-doe", "-verbose", "-cp",
+ largeJar.getAbsolutePath(), testFile.getAbsolutePath())) {
+ throw new IOException("test failed");
+ }
+ } finally {
+ Utils.deleteFile(largeJar);
+ }
+ }
+
+ // a jar with an enormous file + a class file for the existential test
+ public static void testScenarioB(String... args) throws IOException {
+ final File largeJar = new File("huge.jar");
+ final File javaFile = new File("Foo.java");
+
+ final Path path = largeJar.getAbsoluteFile().getParentFile().toPath();
+ final long available = Files.getFileStore(path).getUsableSpace();
+ final long MAX_VALUE = 0xFFFF_FFFFL;
+
+ final long absolute = MAX_VALUE + 1L;
+ final long required = (long)(absolute * 1.1); // pad for sundries
+ System.out.println("\tavailable: " + available / GIGA + " GB");
+ System.out.println("\trequired: " + required / GIGA + " GB");
+
+ if (available > required) {
+ createJarWithLargeFile(largeJar, javaFile, absolute);
+ File testFile = new File("Bar.java");
+ Utils.createJavaFile(testFile, javaFile);
+ try {
+ if (!Utils.compile("-doe", "-verbose", "-cp",
+ largeJar.getAbsolutePath(), testFile.getAbsolutePath())) {
+ throw new IOException("test failed");
+ }
+ } finally {
+ Utils.deleteFile(largeJar);
+ }
+ } else {
+ System.out.println("Warning: testScenarioB passes vacuously," +
+ " requirements exceeds available space");
+ }
+ }
+
+ public static void main(String... args) throws IOException {
+ testScenarioA();
+ System.out.println("testScenarioA: PASS");
+ if (Boolean.getBoolean("T6836682.testScenarioB")) {
+ testScenarioB();
+ System.out.println("testScenarioB: PASS");
+ } else {
+ System.out.println("Warning: testScenarioB, large file test skipped");
+ }
+ }
+}
diff --git a/langtools/test/tools/javac/file/zip/T6865530.java b/langtools/test/tools/javac/file/zip/T6865530.java
new file mode 100644
index 00000000000..62d410429a6
--- /dev/null
+++ b/langtools/test/tools/javac/file/zip/T6865530.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6865530
+ * @summary ensure JavacFileManager handles non-standard zipfiles.
+ * @compile -XDignore.symbol.file T6865530.java
+ * @run main T6865530
+ */
+
+
+import java.io.File;
+
+
+public class T6865530 {
+
+ public static void main(String... args) throws Exception {
+ File badFile = new File("bad.exe");
+ File testJar = new File("test.jar");
+ File fooJava = new File("Foo.java");
+ File barJava = new File("Bar.java");
+
+ // create a jar by compiling a file, and append the jar to some
+ // arbitrary data to offset the start of the zip/jar archive
+ Utils.createJavaFile(fooJava);
+ Utils.compile("-doe", "-verbose", fooJava.getName());
+ String[] jarArgs = {
+ "cvf", testJar.getAbsolutePath(), "Foo.class"
+ };
+ Utils.jarTool.run(jarArgs);
+ Utils.cat(badFile, fooJava, testJar);
+
+ // create test file and use the above file as a classpath
+ Utils.createJavaFile(barJava);
+ try {
+ if (!Utils.compile("-doe", "-verbose", "-cp", badFile.getAbsolutePath(), "Bar.java")) {
+ throw new RuntimeException("test fails javac did not compile");
+ }
+ } finally {
+ Utils.deleteFile(badFile);
+ Utils.deleteFile(testJar);
+ }
+ }
+}
+
diff --git a/langtools/test/tools/javac/file/zip/Utils.java b/langtools/test/tools/javac/file/zip/Utils.java
new file mode 100644
index 00000000000..2f5f31b329b
--- /dev/null
+++ b/langtools/test/tools/javac/file/zip/Utils.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011, 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.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class Utils {
+
+ static final sun.tools.jar.Main jarTool =
+ new sun.tools.jar.Main(System.out, System.err, "jar-tool");
+
+ static final com.sun.tools.javac.Main javac =
+ new com.sun.tools.javac.Main();
+
+ private Utils(){}
+
+ public static boolean compile(String... args) {
+ return javac.compile(args) == 0;
+ }
+
+ public static void createClassFile(File javaFile, File superClass,
+ boolean delete) throws IOException {
+ createJavaFile(javaFile, superClass);
+ if (!compile(javaFile.getName())) {
+ throw new RuntimeException("compile failed unexpectedly");
+ }
+ if (delete) javaFile.delete();
+ }
+
+ public static void createJavaFile(File outFile) throws IOException {
+ createJavaFile(outFile, null);
+ }
+
+ public static void createJavaFile(File outFile, File superClass) throws IOException {
+ PrintStream ps = null;
+ String srcStr = "public class " + getSimpleName(outFile) + " ";
+ if (superClass != null) {
+ srcStr = srcStr.concat("extends " + getSimpleName(superClass) + " ");
+ }
+ srcStr = srcStr.concat("{}");
+ try {
+ FileOutputStream fos = new FileOutputStream(outFile);
+ ps = new PrintStream(fos);
+ ps.println(srcStr);
+ } finally {
+ close(ps);
+ }
+ }
+
+ static String getClassFileName(File javaFile) {
+ return javaFile.getName().endsWith(".java")
+ ? javaFile.getName().replace(".java", ".class")
+ : null;
+ }
+
+ static String getSimpleName(File inFile) {
+ String fname = inFile.getName();
+ return fname.substring(0, fname.indexOf("."));
+ }
+
+ public static void copyStream(InputStream in, OutputStream out) throws IOException {
+ byte[] buf = new byte[8192];
+ int n = in.read(buf);
+ while (n > 0) {
+ out.write(buf, 0, n);
+ n = in.read(buf);
+ }
+ }
+
+ public static void close(Closeable c) {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (IOException ignore) {}
+ }
+ }
+
+ public static void deleteFile(File f) {
+ if (!f.delete()) {
+ throw new RuntimeException("could not delete file: " + f.getAbsolutePath());
+ }
+ }
+
+ public static void cat(File output, File... files) throws IOException {
+ BufferedInputStream bis = null;
+ BufferedOutputStream bos = null;
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(output);
+ bos = new BufferedOutputStream(fos);
+ for (File x : files) {
+ FileInputStream fis = new FileInputStream(x);
+ bis = new BufferedInputStream(fis);
+ copyStream(bis, bos);
+ Utils.close(bis);
+ }
+ } finally {
+ Utils.close(bis);
+ Utils.close(bos);
+ Utils.close(fos);
+ }
+ }
+}
diff --git a/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java b/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
index 2706782b10d..4960cacde5e 100644
--- a/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
+++ b/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -24,8 +24,6 @@
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
-import static javax.lang.model.SourceVersion.*;
-import javax.lang.model.element.*;
import javax.lang.model.util.*;
/**
diff --git a/langtools/test/tools/javac/processing/6430209/b6341534.java b/langtools/test/tools/javac/processing/6430209/b6341534.java
index 5dfad046c90..567a02484be 100644
--- a/langtools/test/tools/javac/processing/6430209/b6341534.java
+++ b/langtools/test/tools/javac/processing/6430209/b6341534.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2011, 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
@@ -56,7 +56,9 @@ public class b6341534 extends JavacTestingAbstractProcessor {
// on round 1, expect errorRaised == false && processingOver == false
// on round 2, expect errorRaised == true && processingOver == true
if( renv.errorRaised() != renv.processingOver()) {
- messager.printMessage(ERROR, "FAILED");
+ messager.printMessage(ERROR, "FAILED: round:" + r
+ + ", errorRaised:" + renv.errorRaised()
+ + ", processingOver:" + renv.processingOver());
}
return true;
}
diff --git a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out
index 6a48a0e137b..37632783d8f 100644
--- a/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out
+++ b/langtools/test/tools/javac/processing/6994946/SemanticErrorTest.2.out
@@ -1,4 +1,4 @@
SemanticErrorTest.java:11:46: compiler.err.repeated.interface
- compiler.err.proc.messager: Deliberate Error
SemanticErrorTest.java:11:46: compiler.err.repeated.interface
-1 error
+2 errors
diff --git a/langtools/test/tools/javac/processing/environment/round/TestContext.java b/langtools/test/tools/javac/processing/environment/round/TestContext.java
index ddcba25fe80..deed69202bc 100644
--- a/langtools/test/tools/javac/processing/environment/round/TestContext.java
+++ b/langtools/test/tools/javac/processing/environment/round/TestContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -34,7 +34,6 @@ import java.io.*;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
-import javax.tools.*;
import static javax.tools.Diagnostic.Kind.*;
import com.sun.source.util.Trees;
diff --git a/langtools/test/tools/javac/processing/errors/TestErrorCount.java b/langtools/test/tools/javac/processing/errors/TestErrorCount.java
new file mode 100644
index 00000000000..1f40ae8ad58
--- /dev/null
+++ b/langtools/test/tools/javac/processing/errors/TestErrorCount.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6988079
+ * @summary Errors reported via Messager.printMessage(ERROR,"error message") are not tallied correctly
+ * @library ../../lib
+ * @build JavacTestingAbstractProcessor TestErrorCount
+ * @compile/fail/ref=TestErrorCount.out -XDrawDiagnostics -processor TestErrorCount TestErrorCount.java
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+public class TestErrorCount extends JavacTestingAbstractProcessor {
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "intentional error");
+ return true;
+ }
+}
+
diff --git a/langtools/test/tools/javac/processing/errors/TestErrorCount.out b/langtools/test/tools/javac/processing/errors/TestErrorCount.out
new file mode 100644
index 00000000000..ccd4db7e5b2
--- /dev/null
+++ b/langtools/test/tools/javac/processing/errors/TestErrorCount.out
@@ -0,0 +1,3 @@
+- compiler.err.proc.messager: intentional error
+- compiler.err.proc.messager: intentional error
+2 errors
diff --git a/langtools/test/tools/javac/processing/filer/TestPackageInfo.java b/langtools/test/tools/javac/processing/filer/TestPackageInfo.java
index 7a905467370..651f9b7ba45 100644
--- a/langtools/test/tools/javac/processing/filer/TestPackageInfo.java
+++ b/langtools/test/tools/javac/processing/filer/TestPackageInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2011, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6380018 6392177
+ * @bug 6380018 6392177 6993311
* @summary Test the ability to create and process package-info.java files
* @author Joseph D. Darcy
* @library ../../lib
@@ -60,7 +60,7 @@ public class TestPackageInfo extends JavacTestingAbstractProcessor {
// Verify annotations are as expected
Set expectedAnnotations = new HashSet();
- expectedAnnotations.add(eltUtils.getTypeElement("java.lang.SuppressWarnings"));
+ expectedAnnotations.add(eltUtils.getTypeElement("java.lang.Deprecated"));
if (!roundEnv.processingOver()) {
System.out.println("\nRound " + round);
@@ -90,7 +90,7 @@ public class TestPackageInfo extends JavacTestingAbstractProcessor {
} catch(FilerException fe) {}
PrintWriter pw = new PrintWriter(filer.createSourceFile("foo.package-info").openWriter());
- pw.println("@SuppressWarnings(\"\")");
+ pw.println("@Deprecated");
pw.println("package foo;");
pw.close();
diff --git a/langtools/test/tools/javac/processing/filer/foo/bar/package-info.java b/langtools/test/tools/javac/processing/filer/foo/bar/package-info.java
index eb666f4a02e..b4cbbe5803a 100644
--- a/langtools/test/tools/javac/processing/filer/foo/bar/package-info.java
+++ b/langtools/test/tools/javac/processing/filer/foo/bar/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2011, 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
@@ -24,5 +24,5 @@
/**
* Javadoc for the foo.bar package!
*/
-@SuppressWarnings("deprecation")
+@Deprecated
package foo.bar;
diff --git a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java
index d602bc08ead..df7e6d08c9b 100644
--- a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java
+++ b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2011, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6449781
+ * @bug 6449781 6930508
* @summary Test that reported names of anonymous classes are non-null.
* @author Joseph D. Darcy
* @library ../../../lib
@@ -93,6 +93,7 @@ public class TestAnonClassNames {
TestAnonClassNames.class,
};
+ List names = new ArrayList();
for(Class> clazz : classes) {
String name = clazz.getName();
Nesting anno = clazz.getAnnotation(Nesting.class);
@@ -100,7 +101,14 @@ public class TestAnonClassNames {
clazz.getName(),
anno == null ? "(unset/ANONYMOUS)" : anno.value());
testClassName(name);
+ names.add(name);
}
+
+ // test all names together
+ testClassNames(names);
+
+ if (errors > 0)
+ throw new RuntimeException(errors + " errors occurred");
}
/**
@@ -109,15 +117,23 @@ public class TestAnonClassNames {
* input classes are modeled as elements.
*/
static void testClassName(String className) {
- JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
- List classNames = new ArrayList();
- classNames.add(className);
+ testClassNames(Arrays.asList(className));
+ }
+
+ /**
+ * Perform annotation processing on a list of class file names and verify
+ * the existence of different flavors of class names when the
+ * input classes are modeled as elements.
+ */
+ static void testClassNames(List classNames) {
+ System.out.println("test: " + classNames);
List options = new ArrayList();
options.add("-proc:only");
options.add("-classpath");
options.add(System.getProperty("test.classes"));
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
JavaCompiler.CompilationTask compileTask =
javaCompiler.getTask(null, // Output
null, // File manager
@@ -130,9 +146,16 @@ public class TestAnonClassNames {
compileTask.setProcessors(processors);
Boolean goodResult = compileTask.call();
if (!goodResult) {
- throw new RuntimeException("Errors found during compile.");
+ error("Errors found during compile.");
}
}
+
+ static int errors = 0;
+
+ static void error(String msg) {
+ System.out.println("Error: " + msg);
+ errors++;
+ }
}
@Retention(RUNTIME)
diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
index 0bbff60766b..ec1fe05015e 100644
--- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
+++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
@@ -24,7 +24,7 @@
/*
* @test
- * @bug 6639645
+ * @bug 6639645 7026414
* @summary Modeling type implementing missing interfaces
* @library ../../../../lib
* @build JavacTestingAbstractProcessor TestMissingElement
@@ -112,6 +112,7 @@ public class TestMissingElement extends JavacTestingAbstractProcessor {
@Override
public String visitDeclared(DeclaredType t, Void ignore) {
+ checkEqual(t.asElement(), types.asElement(t));
String s = asString(t.asElement());
List extends TypeMirror> args = t.getTypeArguments();
if (!args.isEmpty())
@@ -179,6 +180,13 @@ public class TestMissingElement extends JavacTestingAbstractProcessor {
return (e != null && e.getKind() == ElementKind.PACKAGE
&& ((PackageElement) e).isUnnamed());
}
+
+ void checkEqual(Element e1, Element e2) {
+ if (e1 != e2) {
+ throw new AssertionError("elements not equal as expected: "
+ + e1 + ", " + e2);
+ }
+ }
}
diff --git a/langtools/test/tools/javac/processing/options/testCommandLineClasses/Test.java b/langtools/test/tools/javac/processing/options/testCommandLineClasses/Test.java
new file mode 100644
index 00000000000..f9287e695d8
--- /dev/null
+++ b/langtools/test/tools/javac/processing/options/testCommandLineClasses/Test.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+/*
+ * @test
+ * @bug 6930508
+ * @summary Passing nested class names on javac command line interfere with subsequent name -> class lookup
+ * @library ../../../lib
+ * @build JavacTestingAbstractProcessor p.NestedExamples Test
+ * @run main Test
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.*;
+
+import p.NestedExamples;
+
+public class Test extends JavacTestingAbstractProcessor {
+ public static void main(String... args) throws Exception {
+ new Test().run();
+ }
+
+ void run() throws Exception {
+ NestedExamples e = new NestedExamples();
+ List names = getNames(e.getClasses());
+ test(names);
+ test(reverse(names));
+ names = Arrays.asList(e.getClassNames());
+ test(names);
+ test(reverse(names));
+
+ if (errors > 0)
+ throw new RuntimeException(errors + " errors occurred");
+ }
+
+ List getNames(Class>[] classes) {
+ List names = new ArrayList();
+ for (Class> c: classes)
+ names.add(c.getName());
+ return names;
+ }
+
+ void test(List