This commit is contained in:
Jesper Wilhelmsson 2017-10-04 20:01:19 +00:00
commit eed5d34c26
235 changed files with 7673 additions and 2642 deletions

View file

@ -2160,10 +2160,12 @@ public abstract class ClassLoader {
* if a package of the given {@code name} is already
* defined by this class loader
*
*
* @since 1.2
* @revised 9
* @spec JPMS
*
* @jvms 5.3 Run-time package
* @see <a href="{@docRoot}/../specs/jar/jar.html#sealing">
* The JAR File Specification: Package Sealing</a>
*/
@ -2186,17 +2188,19 @@ public abstract class ClassLoader {
}
/**
* Returns a {@code Package} of the given <a href="#name">name</a> that has been
* defined by this class loader.
* Returns a {@code Package} of the given <a href="#name">name</a> that
* has been defined by this class loader.
*
* @param name The <a href="#name">package name</a>
*
* @return The {@code Package} of the given name defined by this class loader,
* or {@code null} if not found
* @return The {@code Package} of the given name that has been defined
* by this class loader, or {@code null} if not found
*
* @throws NullPointerException
* if {@code name} is {@code null}.
*
* @jvms 5.3 Run-time package
*
* @since 9
* @spec JPMS
*/
@ -2211,14 +2215,18 @@ public abstract class ClassLoader {
}
/**
* Returns all of the {@code Package}s defined by this class loader.
* The returned array has no duplicated {@code Package}s of the same name.
* Returns all of the {@code Package}s that have been defined by
* this class loader. The returned array has no duplicated {@code Package}s
* of the same name.
*
* @apiNote This method returns an array rather than a {@code Set} or {@code Stream}
* for consistency with the existing {@link #getPackages} method.
*
* @return The array of {@code Package} objects defined by this class loader;
* or an zero length array if no package has been defined by this class loader.
* @return The array of {@code Package} objects that have been defined by
* this class loader; or an zero length array if no package has been
* defined by this class loader.
*
* @jvms 5.3 Run-time package
*
* @since 9
* @spec JPMS
@ -2244,7 +2252,7 @@ public abstract class ClassLoader {
* @param name
* The <a href="#name">package name</a>
*
* @return The {@code Package} corresponding to the given name defined by
* @return The {@code Package} of the given name that has been defined by
* this class loader or its ancestors, or {@code null} if not found.
*
* @throws NullPointerException
@ -2263,6 +2271,8 @@ public abstract class ClassLoader {
* {@link ClassLoader#getDefinedPackage} method which returns
* a {@code Package} for the specified class loader.
*
* @see ClassLoader#getDefinedPackage(String)
*
* @since 1.2
* @revised 9
* @spec JPMS
@ -2281,10 +2291,10 @@ public abstract class ClassLoader {
}
/**
* Returns all of the {@code Package}s defined by this class loader
* and its ancestors. The returned array may contain more than one
* {@code Package} object of the same package name, each defined by
* a different class loader in the class loader hierarchy.
* Returns all of the {@code Package}s that have been defined by
* this class loader and its ancestors. The returned array may contain
* more than one {@code Package} object of the same package name, each
* defined by a different class loader in the class loader hierarchy.
*
* @apiNote The {@link #getPlatformClassLoader() platform class loader}
* may delegate to the application class loader. In other words,
@ -2294,8 +2304,10 @@ public abstract class ClassLoader {
* when invoked on the platform class loader, this method will not
* return any packages defined to the application class loader.
*
* @return The array of {@code Package} objects defined by this
* class loader and its ancestors
* @return The array of {@code Package} objects that have been defined by
* this class loader and its ancestors
*
* @see ClassLoader#getDefinedPackages()
*
* @since 1.2
* @revised 9

View file

@ -29,6 +29,7 @@ import jdk.internal.misc.SharedSecrets;
import static java.lang.StackWalker.Option.*;
import java.lang.StackWalker.StackFrame;
import java.lang.invoke.MethodType;
class StackFrameInfo implements StackFrame {
private final static JavaLangInvokeAccess JLIA =
@ -78,6 +79,17 @@ class StackFrameInfo implements StackFrame {
return JLIA.getName(memberName);
}
@Override
public MethodType getMethodType() {
walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
return JLIA.getMethodType(memberName);
}
@Override
public String getDescriptor() {
return JLIA.getMethodDescriptor(memberName);
}
@Override
public int getByteCodeIndex() {
// bci not available for native methods

View file

@ -26,10 +26,12 @@ package java.lang;
import jdk.internal.reflect.CallerSensitive;
import java.util.*;
import java.lang.invoke.MethodType;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
@ -96,7 +98,7 @@ public final class StackWalker {
* @since 9
* @jvms 2.6
*/
public static interface StackFrame {
public interface StackFrame {
/**
* Gets the <a href="ClassLoader.html#name">binary name</a>
* of the declaring class of the method represented by this stack frame.
@ -127,6 +129,47 @@ public final class StackWalker {
*/
public Class<?> getDeclaringClass();
/**
* Returns the {@link MethodType} representing the parameter types and
* the return type for the method represented by this stack frame.
*
* @implSpec
* The default implementation throws {@code UnsupportedOperationException}.
*
* @return the {@code MethodType} for this stack frame
*
* @throws UnsupportedOperationException if this {@code StackWalker}
* is not configured with {@link Option#RETAIN_CLASS_REFERENCE
* Option.RETAIN_CLASS_REFERENCE}.
*
* @since 10
*/
public default MethodType getMethodType() {
throw new UnsupportedOperationException();
}
/**
* Returns the <i>descriptor</i> of the method represented by
* this stack frame as defined by
* <cite>The Java Virtual Machine Specification</cite>.
*
* @implSpec
* The default implementation throws {@code UnsupportedOperationException}.
*
* @return the descriptor of the method represented by
* this stack frame
*
* @see MethodType#fromMethodDescriptorString(String, ClassLoader)
* @see MethodType#toMethodDescriptorString()
* @jvms 4.3.3 Method Descriptor
*
* @since 10
*/
public default String getDescriptor() {
throw new UnsupportedOperationException();
}
/**
* Returns the index to the code array of the {@code Code} attribute
* containing the execution point represented by this stack frame.

View file

@ -28,6 +28,7 @@ package java.lang.invoke;
import java.util.Arrays;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.Kind.*;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeVirtual;
import static java.lang.invoke.MethodHandleStatics.*;
/**
@ -158,8 +159,11 @@ abstract class DelegatingMethodHandle extends MethodHandle {
static final NamedFunction NF_getTarget;
static {
try {
NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
.getDeclaredMethod("getTarget"));
MemberName member = new MemberName(DelegatingMethodHandle.class, "getTarget",
MethodType.methodType(MethodHandle.class), REF_invokeVirtual);
NF_getTarget = new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeVirtual, member, DelegatingMethodHandle.class, NoSuchMethodException.class));
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}

View file

@ -753,42 +753,38 @@ class DirectMethodHandle extends MethodHandle {
return nf;
}
private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
private static NamedFunction createFunction(byte func) {
try {
switch (func) {
case NF_internalMemberName:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("internalMemberName", Object.class));
return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
case NF_internalMemberNameEnsureInit:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("internalMemberNameEnsureInit", Object.class));
return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
case NF_ensureInitialized:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("ensureInitialized", Object.class));
return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
case NF_fieldOffset:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("fieldOffset", Object.class));
return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
case NF_checkBase:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("checkBase", Object.class));
return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
case NF_staticBase:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("staticBase", Object.class));
return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
case NF_staticOffset:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("staticOffset", Object.class));
return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
case NF_checkCast:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("checkCast", Object.class, Object.class));
return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
case NF_allocateInstance:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("allocateInstance", Object.class));
return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
case NF_constructorMethod:
return new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("constructorMethod", Object.class));
return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
case NF_UNSAFE:
return new NamedFunction(new MemberName(MethodHandleStatics.class
.getDeclaredField("UNSAFE")));
MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class));
default:
throw newInternalError("Unknown function: " + func);
}
@ -797,6 +793,15 @@ class DirectMethodHandle extends MethodHandle {
}
}
private static NamedFunction getNamedFunction(String name, MethodType type)
throws ReflectiveOperationException
{
MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeStatic, member, DirectMethodHandle.class, NoSuchMethodException.class));
}
static {
// The Holder class will contain pre-generated DirectMethodHandles resolved
// speculatively using MemberName.getFactory().resolveOrNull. However, that

View file

@ -611,23 +611,17 @@ class Invokers {
try {
switch (func) {
case NF_checkExactType:
return new NamedFunction(Invokers.class
.getDeclaredMethod("checkExactType", MethodHandle.class, MethodType.class));
return getNamedFunction("checkExactType", MethodType.methodType(void.class, MethodHandle.class, MethodType.class));
case NF_checkGenericType:
return new NamedFunction(Invokers.class
.getDeclaredMethod("checkGenericType", MethodHandle.class, MethodType.class));
return getNamedFunction("checkGenericType", MethodType.methodType(MethodHandle.class, MethodHandle.class, MethodType.class));
case NF_getCallSiteTarget:
return new NamedFunction(Invokers.class
.getDeclaredMethod("getCallSiteTarget", CallSite.class));
return getNamedFunction("getCallSiteTarget", MethodType.methodType(MethodHandle.class, CallSite.class));
case NF_checkCustomized:
return new NamedFunction(Invokers.class
.getDeclaredMethod("checkCustomized", MethodHandle.class));
return getNamedFunction("checkCustomized", MethodType.methodType(void.class, MethodHandle.class));
case NF_checkVarHandleGenericType:
return new NamedFunction(Invokers.class
.getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class));
return getNamedFunction("checkVarHandleGenericType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
case NF_checkVarHandleExactType:
return new NamedFunction(Invokers.class
.getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class));
return getNamedFunction("checkVarHandleExactType", MethodType.methodType(MethodHandle.class, VarHandle.class, VarHandle.AccessDescriptor.class));
default:
throw newInternalError("Unknown function: " + func);
}
@ -636,6 +630,15 @@ class Invokers {
}
}
private static NamedFunction getNamedFunction(String name, MethodType type)
throws ReflectiveOperationException
{
MemberName member = new MemberName(Invokers.class, name, type, REF_invokeStatic);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeStatic, member, Invokers.class, NoSuchMethodException.class));
}
private static class Lazy {
private static final MethodHandle MH_asSpreader;

View file

@ -162,6 +162,29 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
return (MethodType) type;
}
/** Return the descriptor of this member, which
* must be a method or constructor.
*/
String getMethodDescriptor() {
if (type == null) {
expandFromVM();
if (type == null) {
return null;
}
}
if (!isInvocable()) {
throw newIllegalArgumentException("not invocable, no method type");
}
// Get a snapshot of type which doesn't get changed by racing threads.
final Object type = this.type;
if (type instanceof String) {
return (String) type;
} else {
return getMethodType().toMethodDescriptorString();
}
}
/** Return the actual type under which this method or constructor must be invoked.
* For non-static methods or constructors, this is the type with a leading parameter,
* a reference to declaring class. For static methods, it is the same as the declared type.

View file

@ -1785,6 +1785,18 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
return memberName.getName();
}
@Override
public MethodType getMethodType(Object mname) {
MemberName memberName = (MemberName)mname;
return memberName.getMethodType();
}
@Override
public String getMethodDescriptor(Object mname) {
MemberName memberName = (MemberName)mname;
return memberName.getMethodDescriptor();
}
@Override
public boolean isNative(Object mname) {
MemberName memberName = (MemberName)mname;

View file

@ -211,7 +211,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
}
/**
* Increments i, mod modulus.
* Circularly increments i, mod modulus.
* Precondition and postcondition: 0 <= i < modulus.
*/
static final int inc(int i, int modulus) {
@ -220,7 +220,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
}
/**
* Decrements i, mod modulus.
* Circularly decrements i, mod modulus.
* Precondition and postcondition: 0 <= i < modulus.
*/
static final int dec(int i, int modulus) {
@ -233,7 +233,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
* Precondition: 0 <= i < modulus, 0 <= distance <= modulus.
* @return index 0 <= i < modulus
*/
static final int add(int i, int distance, int modulus) {
static final int inc(int i, int distance, int modulus) {
if ((i += distance) - modulus >= 0) i -= modulus;
return i;
}
@ -825,7 +825,7 @@ public class ArrayDeque<E> extends AbstractCollection<E>
final int i, n;
return ((n = sub(getFence(), i = cursor, es.length) >> 1) <= 0)
? null
: new DeqSpliterator(i, cursor = add(i, n, es.length));
: new DeqSpliterator(i, cursor = inc(i, n, es.length));
}
public void forEachRemaining(Consumer<? super E> action) {

View file

@ -490,7 +490,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Implements Map.putAll and Map constructor
* Implements Map.putAll and Map constructor.
*
* @param m the map
* @param evict false when initially constructing this map, else
@ -557,7 +557,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Implements Map.get and related methods
* Implements Map.get and related methods.
*
* @param hash hash for key
* @param key the key
@ -612,7 +612,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Implements Map.put and related methods
* Implements Map.put and related methods.
*
* @param hash hash for key
* @param key the key
@ -700,7 +700,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
@ -800,7 +800,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Implements Map.remove and related methods
* Implements Map.remove and related methods.
*
* @param hash hash for key
* @param key the key
@ -875,7 +875,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
public boolean containsValue(Object value) {
Node<K,V>[] tab; V v;
if ((tab = table) != null && size > 0) {
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next) {
if ((v = e.value) == value ||
(value != null && value.equals(v)))
@ -927,7 +927,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e.key);
}
@ -975,7 +975,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e.value);
}
@ -1038,7 +1038,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e);
}
@ -1335,7 +1335,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e.key, e.value);
}
@ -1351,7 +1351,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next) {
e.value = function.apply(e.key, e.value);
}
@ -1394,9 +1394,10 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Save the state of the {@code HashMap} instance to a stream (i.e.,
* serialize it).
* Saves this map to a stream (that is, serializes it).
*
* @param s the stream
* @throws IOException if an I/O error occurs
* @serialData The <i>capacity</i> of the HashMap (the length of the
* bucket array) is emitted (int), followed by the
* <i>size</i> (an int, the number of key-value
@ -1415,8 +1416,11 @@ public class HashMap<K,V> extends AbstractMap<K,V>
}
/**
* Reconstitute the {@code HashMap} instance from a stream (i.e.,
* deserialize it).
* Reconstitutes this map from a stream (that is, deserializes it).
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found
* @throws IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
@ -1445,7 +1449,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
table = tab;
// Read the keys and values, and put the mappings in the HashMap
@ -1830,7 +1834,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
Node<K,V>[] tab;
if (size > 0 && (tab = table) != null) {
for (Node<K, V> e : tab) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next) {
s.writeObject(e.key);
s.writeObject(e.value);
@ -1951,7 +1955,6 @@ public class HashMap<K,V> extends AbstractMap<K,V>
/**
* Forms tree of the nodes linked from this node.
* @return root of tree
*/
final void treeify(Node<K,V>[] tab) {
TreeNode<K,V> root = null;
@ -2089,8 +2092,11 @@ public class HashMap<K,V> extends AbstractMap<K,V>
return;
if (root.parent != null)
root = root.root();
if (root == null || root.right == null ||
(rl = root.left) == null || rl.left == null) {
if (root == null
|| (movable
&& (root.right == null
|| (rl = root.left) == null
|| rl.left == null))) {
tab[index] = first.untreeify(map); // too small
return;
}
@ -2319,7 +2325,7 @@ public class HashMap<K,V> extends AbstractMap<K,V>
static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
TreeNode<K,V> x) {
for (TreeNode<K,V> xp, xpl, xpr;;) {
for (TreeNode<K,V> xp, xpl, xpr;;) {
if (x == null || x == root)
return root;
else if ((xp = x.parent) == null) {

View file

@ -2490,13 +2490,13 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
for (Completion p = stack; p != null; p = p.next)
++count;
return super.toString() +
((r == null) ?
((count == 0) ?
"[Not completed]" :
"[Not completed, " + count + " dependents]") :
(((r instanceof AltResult) && ((AltResult)r).ex != null) ?
"[Completed exceptionally]" :
"[Completed normally]"));
((r == null)
? ((count == 0)
? "[Not completed]"
: "[Not completed, " + count + " dependents]")
: (((r instanceof AltResult) && ((AltResult)r).ex != null)
? "[Completed exceptionally: " + ((AltResult)r).ex + "]"
: "[Completed normally]"));
}
// jdk9 additions

View file

@ -1394,8 +1394,8 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
/**
* Saves the state of the {@code ConcurrentHashMap} instance to a
* stream (i.e., serializes it).
* Saves this map to a stream (that is, serializes it).
*
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
* @serialData
@ -1439,7 +1439,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
* Reconstitutes this map from a stream (that is, deserializes it).
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found

View file

@ -174,6 +174,10 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
this.completionQueue = completionQueue;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
@ -181,6 +185,10 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
return f;
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<V> submit(Runnable task, V result) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task, result);

View file

@ -514,6 +514,9 @@ public class Executors {
task.run();
return result;
}
public String toString() {
return super.toString() + "[Wrapped task = " + task + "]";
}
}
/**
@ -540,6 +543,10 @@ public class Executors {
throw e.getException();
}
}
public String toString() {
return super.toString() + "[Wrapped task = " + task + "]";
}
}
/**
@ -592,6 +599,10 @@ public class Executors {
throw e.getException();
}
}
public String toString() {
return super.toString() + "[Wrapped task = " + task + "]";
}
}
/**

View file

@ -1375,6 +1375,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
public final void setRawResult(T v) { result = v; }
public final boolean exec() { runnable.run(); return true; }
public final void run() { invoke(); }
public String toString() {
return super.toString() + "[Wrapped task = " + runnable + "]";
}
private static final long serialVersionUID = 5232453952276885070L;
}
@ -1392,6 +1395,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
public final void setRawResult(Void v) { }
public final boolean exec() { runnable.run(); return true; }
public final void run() { invoke(); }
public String toString() {
return super.toString() + "[Wrapped task = " + runnable + "]";
}
private static final long serialVersionUID = 5232453952276885070L;
}
@ -1437,6 +1443,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
}
public final void run() { invoke(); }
public String toString() {
return super.toString() + "[Wrapped task = " + callable + "]";
}
private static final long serialVersionUID = 2838392045355241008L;
}

View file

@ -480,6 +480,41 @@ public class FutureTask<V> implements RunnableFuture<V> {
}
}
/**
* Returns a string representation of this FutureTask.
*
* @implSpec
* The default implementation returns a string identifying this
* FutureTask, as well as its completion state. The state, in
* brackets, contains one of the strings {@code "Completed Normally"},
* {@code "Completed Exceptionally"}, {@code "Cancelled"}, or {@code
* "Not completed"}.
*
* @return a string representation of this FutureTask
*/
public String toString() {
final String status;
switch (state) {
case NORMAL:
status = "[Completed normally]";
break;
case EXCEPTIONAL:
status = "[Completed exceptionally: " + outcome + "]";
break;
case CANCELLED:
case INTERRUPTING:
case INTERRUPTED:
status = "[Cancelled]";
break;
default:
final Callable<?> callable = this.callable;
status = (callable == null)
? "[Not completed]"
: "[Not completed, task = " + callable + "]";
}
return super.toString() + status;
}
// VarHandle mechanics
private static final VarHandle STATE;
private static final VarHandle RUNNER;

View file

@ -383,7 +383,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
@ -393,8 +393,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int runStateOf(int c) { return c & ~COUNT_MASK; }
private static int workerCountOf(int c) { return c & COUNT_MASK; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
/*
@ -434,7 +434,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* decrements are performed within getTask.
*/
private void decrementWorkerCount() {
do {} while (! compareAndDecrementWorkerCount(ctl.get()));
ctl.addAndGet(-1);
}
/**
@ -538,12 +538,17 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* Core pool size is the minimum number of workers to keep alive
* (and not allow to time out etc) unless allowCoreThreadTimeOut
* is set, in which case the minimum is zero.
*
* Since the worker count is actually stored in COUNT_BITS bits,
* the effective limit is {@code corePoolSize & COUNT_MASK}.
*/
private volatile int corePoolSize;
/**
* Maximum pool size. Note that the actual maximum is internally
* bounded by CAPACITY.
* Maximum pool size.
*
* Since the worker count is actually stored in COUNT_BITS bits,
* the effective limit is {@code maximumPoolSize & COUNT_MASK}.
*/
private volatile int maximumPoolSize;
@ -705,7 +710,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
(runStateLessThan(c, STOP) && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
@ -744,17 +749,12 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* specially.
*/
private void checkShutdownAccess() {
// assert mainLock.isHeldByCurrentThread();
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
for (Worker w : workers)
security.checkAccess(w.thread);
}
}
@ -763,14 +763,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* (in which case some threads may remain uninterrupted).
*/
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
// assert mainLock.isHeldByCurrentThread();
for (Worker w : workers)
w.interruptIfStarted();
}
/**
@ -896,26 +891,22 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*/
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
for (int c = ctl.get();;) {
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP)
|| firstTask != null
|| workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
if (workerCountOf(c)
>= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
if (runStateAtLeast(c, SHUTDOWN))
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
@ -934,10 +925,10 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
int c = ctl.get();
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (isRunning(c) ||
(runStateLessThan(c, STOP) && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
@ -1044,10 +1035,10 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP) || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
@ -1140,17 +1131,12 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
afterExecute(task, null);
} catch (Throwable ex) {
afterExecute(task, ex);
throw ex;
}
} finally {
task = null;
@ -1331,7 +1317,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*
* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current {@code RejectedExecutionHandler}.
* the task is handled by the current {@link RejectedExecutionHandler}.
*
* @param command the task to execute
* @throws RejectedExecutionException at discretion of
@ -1438,7 +1424,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
public boolean isShutdown() {
return ! isRunning(ctl.get());
return runStateAtLeast(ctl.get(), SHUTDOWN);
}
/** Used by ScheduledThreadPoolExecutor. */
@ -1459,7 +1445,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*/
public boolean isTerminating() {
int c = ctl.get();
return ! isRunning(c) && runStateLessThan(c, TERMINATED);
return runStateAtLeast(c, SHUTDOWN) && runStateLessThan(c, TERMINATED);
}
public boolean isTerminated() {
@ -1472,7 +1458,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
while (!runStateAtLeast(ctl.get(), TERMINATED)) {
while (runStateLessThan(ctl.get(), TERMINATED)) {
if (nanos <= 0L)
return false;
nanos = termination.awaitNanos(nanos);
@ -1951,7 +1937,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
int c = ctl.get();
String runState =
runStateLessThan(c, SHUTDOWN) ? "Running" :
isRunning(c) ? "Running" :
runStateAtLeast(c, TERMINATED) ? "Terminated" :
"Shutting down";
return super.toString() +

View file

@ -342,11 +342,13 @@ public enum TimeUnit {
* using:
*
* <pre> {@code
* public synchronized Object poll(long timeout, TimeUnit unit)
* public E poll(long timeout, TimeUnit unit)
* throws InterruptedException {
* while (empty) {
* unit.timedWait(this, timeout);
* ...
* synchronized (lock) {
* while (isEmpty()) {
* unit.timedWait(lock, timeout);
* ...
* }
* }
* }}</pre>
*

View file

@ -67,11 +67,11 @@ public abstract class AbstractQueuedLongSynchronizer
private static final long serialVersionUID = 7373984972572414692L;
/*
To keep sources in sync, the remainder of this source file is
exactly cloned from AbstractQueuedSynchronizer, replacing class
name and changing ints related with sync state to longs. Please
keep it that way.
*/
* To keep sources in sync, the remainder of this source file is
* exactly cloned from AbstractQueuedSynchronizer, replacing class
* name and changing ints related with sync state to longs. Please
* keep it that way.
*/
/**
* Creates a new {@code AbstractQueuedLongSynchronizer} instance
@ -725,8 +725,7 @@ public abstract class AbstractQueuedLongSynchronizer
/**
* Returns {@code true} if synchronization is held exclusively with
* respect to the current (calling) thread. This method is invoked
* upon each call to a non-waiting {@link ConditionObject} method.
* (Waiting methods instead invoke {@link #release}.)
* upon each call to a {@link ConditionObject} method.
*
* <p>The default implementation throws {@link
* UnsupportedOperationException}. This method is invoked
@ -1366,9 +1365,8 @@ public abstract class AbstractQueuedLongSynchronizer
}
/**
* Condition implementation for a {@link
* AbstractQueuedLongSynchronizer} serving as the basis of a {@link
* Lock} implementation.
* Condition implementation for a {@link AbstractQueuedLongSynchronizer}
* serving as the basis of a {@link Lock} implementation.
*
* <p>Method documentation for this class describes mechanics,
* not behavioral specifications from the point of view of Lock
@ -1401,6 +1399,8 @@ public abstract class AbstractQueuedLongSynchronizer
* @return its new wait node
*/
private Node addConditionWaiter() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {

View file

@ -194,19 +194,13 @@ import java.util.concurrent.TimeUnit;
* represent the locked state. While a non-reentrant lock
* does not strictly require recording of the current owner
* thread, this class does so anyway to make usage easier to monitor.
* It also supports conditions and exposes
* one of the instrumentation methods:
* It also supports conditions and exposes some instrumentation methods:
*
* <pre> {@code
* class Mutex implements Lock, java.io.Serializable {
*
* // Our internal helper class
* private static class Sync extends AbstractQueuedSynchronizer {
* // Reports whether in locked state
* protected boolean isHeldExclusively() {
* return getState() == 1;
* }
*
* // Acquires the lock if state is zero
* public boolean tryAcquire(int acquires) {
* assert acquires == 1; // Otherwise unused
@ -220,14 +214,27 @@ import java.util.concurrent.TimeUnit;
* // Releases the lock by setting state to zero
* protected boolean tryRelease(int releases) {
* assert releases == 1; // Otherwise unused
* if (getState() == 0) throw new IllegalMonitorStateException();
* if (!isHeldExclusively())
* throw new IllegalMonitorStateException();
* setExclusiveOwnerThread(null);
* setState(0);
* return true;
* }
*
* // Reports whether in locked state
* public boolean isLocked() {
* return getState() != 0;
* }
*
* public boolean isHeldExclusively() {
* // a data race, but safe due to out-of-thin-air guarantees
* return getExclusiveOwnerThread() == Thread.currentThread();
* }
*
* // Provides a Condition
* Condition newCondition() { return new ConditionObject(); }
* public Condition newCondition() {
* return new ConditionObject();
* }
*
* // Deserializes properly
* private void readObject(ObjectInputStream s)
@ -240,12 +247,17 @@ import java.util.concurrent.TimeUnit;
* // The sync object does all the hard work. We just forward to it.
* private final Sync sync = new Sync();
*
* public void lock() { sync.acquire(1); }
* public boolean tryLock() { return sync.tryAcquire(1); }
* public void unlock() { sync.release(1); }
* public Condition newCondition() { return sync.newCondition(); }
* public boolean isLocked() { return sync.isHeldExclusively(); }
* public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
* public void lock() { sync.acquire(1); }
* public boolean tryLock() { return sync.tryAcquire(1); }
* public void unlock() { sync.release(1); }
* public Condition newCondition() { return sync.newCondition(); }
* public boolean isLocked() { return sync.isLocked(); }
* public boolean isHeldByCurrentThread() {
* return sync.isHeldExclusively();
* }
* public boolean hasQueuedThreads() {
* return sync.hasQueuedThreads();
* }
* public void lockInterruptibly() throws InterruptedException {
* sync.acquireInterruptibly(1);
* }
@ -1193,8 +1205,7 @@ public abstract class AbstractQueuedSynchronizer
/**
* Returns {@code true} if synchronization is held exclusively with
* respect to the current (calling) thread. This method is invoked
* upon each call to a non-waiting {@link ConditionObject} method.
* (Waiting methods instead invoke {@link #release}.)
* upon each call to a {@link ConditionObject} method.
*
* <p>The default implementation throws {@link
* UnsupportedOperationException}. This method is invoked
@ -1834,9 +1845,8 @@ public abstract class AbstractQueuedSynchronizer
}
/**
* Condition implementation for a {@link
* AbstractQueuedSynchronizer} serving as the basis of a {@link
* Lock} implementation.
* Condition implementation for a {@link AbstractQueuedSynchronizer}
* serving as the basis of a {@link Lock} implementation.
*
* <p>Method documentation for this class describes mechanics,
* not behavioral specifications from the point of view of Lock
@ -1867,6 +1877,8 @@ public abstract class AbstractQueuedSynchronizer
* @return its new wait node
*/
private Node addConditionWaiter() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {

View file

@ -73,7 +73,7 @@ import java.util.concurrent.TimeUnit;
* available in the buffer. This can be achieved using two
* {@link Condition} instances.
* <pre>
* class BoundedBuffer {
* class BoundedBuffer&lt;E&gt; {
* <b>final Lock lock = new ReentrantLock();</b>
* final Condition notFull = <b>lock.newCondition(); </b>
* final Condition notEmpty = <b>lock.newCondition(); </b>
@ -81,7 +81,7 @@ import java.util.concurrent.TimeUnit;
* final Object[] items = new Object[100];
* int putptr, takeptr, count;
*
* public void put(Object x) throws InterruptedException {
* public void put(E x) throws InterruptedException {
* <b>lock.lock();
* try {</b>
* while (count == items.length)
@ -95,12 +95,12 @@ import java.util.concurrent.TimeUnit;
* }</b>
* }
*
* public Object take() throws InterruptedException {
* public E take() throws InterruptedException {
* <b>lock.lock();
* try {</b>
* while (count == 0)
* <b>notEmpty.await();</b>
* Object x = items[takeptr];
* E x = (E) items[takeptr];
* if (++takeptr == items.length) takeptr = 0;
* --count;
* <b>notFull.signal();</b>
@ -310,7 +310,8 @@ public interface Condition {
* the following form:
*
* <pre> {@code
* boolean aMethod(long timeout, TimeUnit unit) {
* boolean aMethod(long timeout, TimeUnit unit)
* throws InterruptedException {
* long nanos = unit.toNanos(timeout);
* lock.lock();
* try {
@ -320,6 +321,7 @@ public interface Condition {
* nanos = theCondition.awaitNanos(nanos);
* }
* // ...
* return true;
* } finally {
* lock.unlock();
* }
@ -410,7 +412,8 @@ public interface Condition {
* <p>The return value indicates whether the deadline has elapsed,
* which can be used as follows:
* <pre> {@code
* boolean aMethod(Date deadline) {
* boolean aMethod(Date deadline)
* throws InterruptedException {
* boolean stillWaiting = true;
* lock.lock();
* try {
@ -420,6 +423,7 @@ public interface Condition {
* stillWaiting = theCondition.awaitUntil(deadline);
* }
* // ...
* return true;
* } finally {
* lock.unlock();
* }

View file

@ -151,18 +151,20 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
* }
*
* double distanceFromOrigin() { // A read-only method
* double currentX, currentY;
* long stamp = sl.tryOptimisticRead();
* double currentX = x, currentY = y;
* if (!sl.validate(stamp)) {
* stamp = sl.readLock();
* do {
* if (stamp == 0L)
* stamp = sl.readLock();
* try {
* // possibly racy reads
* currentX = x;
* currentY = y;
* } finally {
* sl.unlockRead(stamp);
* stamp = sl.tryConvertToOptimisticRead(stamp);
* }
* }
* return Math.sqrt(currentX * currentX + currentY * currentY);
* } while (stamp == 0);
* return Math.hypot(currentX, currentY);
* }
*
* void moveIfAtOrigin(double newX, double newY) { // upgrade