< prev index next >
src/java.base/share/classes/java/lang/Thread.java
Print this page
imported patch Thread-misc
*** 37,46 ****
--- 37,47 ----
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
import jdk.internal.misc.TerminatingThreadLocal;
+ import jdk.internal.misc.Unsafe;
import sun.nio.ch.Interruptible;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import sun.security.util.SecurityConstants;
import jdk.internal.HotSpotIntrinsicCandidate;
*** 146,163 ****
private static native void registerNatives();
static {
registerNatives();
}
! private volatile String name;
private int priority;
/* Whether or not the thread is a daemon thread. */
! private boolean daemon = false;
/* Fields reserved for exclusive use by the JVM */
! private boolean stillborn = false;
private long eetop;
/* What will be run. */
private Runnable target;
--- 147,164 ----
private static native void registerNatives();
static {
registerNatives();
}
! private String name;
private int priority;
/* Whether or not the thread is a daemon thread. */
! private boolean daemon; // by default false;
/* Fields reserved for exclusive use by the JVM */
! private boolean stillborn;
private long eetop;
/* What will be run. */
private Runnable target;
*** 174,192 ****
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
! ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
! ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
--- 175,209 ----
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
+ private static final Unsafe U = Unsafe.getUnsafe();
+ private static final long DAEMON = U.objectFieldOffset(
+ Thread.class, "daemon");
+ private static final long CONTEXTCLASSLOADER = U.objectFieldOffset(
+ Thread.class, "contextClassLoader");
+ private static final long UNCAUGHTEXCEPTIONHANDLER = U.objectFieldOffset(
+ Thread.class, "uncaughtExceptionHandler");
+ private static final long PRIORITY = U.objectFieldOffset(
+ Thread.class, "priority");
+ private static final long NAME = U.objectFieldOffset(
+ Thread.class, "name");
+
+ private ClassLoader contextClassLoaderAcquire() {
+ return (ClassLoader) U.getReferenceAcquire(this, CONTEXTCLASSLOADER);
+ }
+
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
! ThreadLocal.ThreadLocalMap threadLocals;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
! ThreadLocal.ThreadLocalMap inheritableThreadLocals;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*** 436,449 ****
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
! if (security == null || isCCLOverridden(parent.getClass()))
! this.contextClassLoader = parent.getContextClassLoader();
! else
! this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
--- 453,466 ----
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
! this.contextClassLoader =
! (security == null || isCCLOverridden(parent.getClass()))
! ? parent.getContextClassLoader()
! : parent.contextClassLoaderAcquire();
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
*** 452,461 ****
--- 469,480 ----
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
this.tid = nextThreadID();
+
+ U.storeFence();
}
/**
* Throws CloneNotSupportedException as a Thread can not be meaningfully
* cloned. Construct a new Thread instead.
*** 1143,1164 ****
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
! setPriority0(priority = newPriority);
}
}
/**
* Returns this thread's priority.
*
* @return this thread's priority.
* @see #setPriority
*/
public final int getPriority() {
! return priority;
}
/**
* Changes the name of this thread to be equal to the argument {@code name}.
* <p>
--- 1162,1184 ----
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
! U.putIntRelease(this, PRIORITY, newPriority);
! setPriority0(newPriority);
}
}
/**
* Returns this thread's priority.
*
* @return this thread's priority.
* @see #setPriority
*/
public final int getPriority() {
! return U.getIntAcquire(this, PRIORITY);
}
/**
* Changes the name of this thread to be equal to the argument {@code name}.
* <p>
*** 1170,1199 ****
* @throws SecurityException if the current thread cannot modify this
* thread.
* @see #getName
* @see #checkAccess()
*/
! public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
/**
* Returns this thread's name.
*
* @return this thread's name.
* @see #setName(String)
*/
public final String getName() {
! return name;
}
/**
* Returns the thread group to which this thread belongs.
* This method returns null if this thread has died
--- 1190,1222 ----
* @throws SecurityException if the current thread cannot modify this
* thread.
* @see #getName
* @see #checkAccess()
*/
! public final void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
+ synchronized (this) {
this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}
+ U.storeFence();
+ }
/**
* Returns this thread's name.
*
* @return this thread's name.
* @see #setName(String)
*/
public final String getName() {
! return (String) U.getReferenceAcquire(this, NAME);
}
/**
* Returns the thread group to which this thread belongs.
* This method returns null if this thread has died
*** 1336,1346 ****
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
! public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
--- 1359,1369 ----
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
! public final void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
*** 1404,1425 ****
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
! daemon = on;
}
/**
* Tests if this thread is a daemon thread.
*
* @return {@code true} if this thread is a daemon thread;
* {@code false} otherwise.
* @see #setDaemon(boolean)
*/
public final boolean isDaemon() {
! return daemon;
}
/**
* Determines if the currently running thread has permission to
* modify this thread.
--- 1427,1448 ----
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
! U.putBooleanRelease(this, DAEMON, on);
}
/**
* Tests if this thread is a daemon thread.
*
* @return {@code true} if this thread is a daemon thread;
* {@code false} otherwise.
* @see #setDaemon(boolean)
*/
public final boolean isDaemon() {
! return U.getBooleanAcquire(this, DAEMON);
}
/**
* Determines if the currently running thread has permission to
* modify this thread.
*** 1445,1461 ****
*
* @return a string representation of this thread.
*/
public String toString() {
ThreadGroup group = getThreadGroup();
! if (group != null) {
! return "Thread[" + getName() + "," + getPriority() + "," +
! group.getName() + "]";
! } else {
! return "Thread[" + getName() + "," + getPriority() + "," +
! "" + "]";
! }
}
/**
* Returns the context {@code ClassLoader} for this thread. The context
* {@code ClassLoader} is provided by the creator of the thread for use
--- 1468,1479 ----
*
* @return a string representation of this thread.
*/
public String toString() {
ThreadGroup group = getThreadGroup();
! return "Thread[" + getName() + "," + getPriority() + ","
! + ((group != null) ? group.getName() : null) + "]";
}
/**
* Returns the context {@code ClassLoader} for this thread. The context
* {@code ClassLoader} is provided by the creator of the thread for use
*** 1479,1496 ****
*
* @since 1.2
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
! if (contextClassLoader == null)
! return null;
! SecurityManager sm = System.getSecurityManager();
! if (sm != null) {
! ClassLoader.checkClassLoaderPermission(contextClassLoader,
! Reflection.getCallerClass());
! }
! return contextClassLoader;
}
/**
* Sets the context ClassLoader for this Thread. The context
* ClassLoader can be set when a thread is created, and allows
--- 1497,1511 ----
*
* @since 1.2
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
! SecurityManager sm;
! ClassLoader cl = contextClassLoaderAcquire();
! if (cl != null && (sm = System.getSecurityManager()) != null)
! ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
! return cl;
}
/**
* Sets the context ClassLoader for this Thread. The context
* ClassLoader can be set when a thread is created, and allows
*** 1516,1526 ****
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
! contextClassLoader = cl;
}
/**
* Returns {@code true} if and only if the current thread holds the
* monitor lock on the specified object.
--- 1531,1541 ----
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
! U.putReferenceRelease(this, CONTEXTCLASSLOADER, cl);
}
/**
* Returns {@code true} if and only if the current thread holds the
* monitor lock on the specified object.
*** 1855,1866 ****
public State getState() {
// get current thread state
return jdk.internal.misc.VM.toThreadState(threadStatus);
}
- // Added in JSR-166
-
/**
* Interface for handlers invoked when a {@code Thread} abruptly
* terminates due to an uncaught exception.
* <p>When a thread is about to terminate due to an uncaught exception
* the Java Virtual Machine will query the thread for its
--- 1870,1879 ----
*** 1893,1903 ****
*/
void uncaughtException(Thread t, Throwable e);
}
// null unless explicitly set
! private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
--- 1906,1916 ----
*/
void uncaughtException(Thread t, Throwable e);
}
// null unless explicitly set
! private UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
*** 1964,1975 ****
* has terminated, in which case {@code null} is returned.
* @since 1.5
* @return the uncaught exception handler for this thread
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
! return uncaughtExceptionHandler != null ?
! uncaughtExceptionHandler : group;
}
/**
* Set the handler invoked when this thread abruptly terminates
* due to an uncaught exception.
--- 1977,1989 ----
* has terminated, in which case {@code null} is returned.
* @since 1.5
* @return the uncaught exception handler for this thread
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
! UncaughtExceptionHandler ueh = (UncaughtExceptionHandler)
! U.getReferenceAcquire(this, UNCAUGHTEXCEPTIONHANDLER);
! return (ueh != null) ? ueh : group;
}
/**
* Set the handler invoked when this thread abruptly terminates
* due to an uncaught exception.
*** 1985,1995 ****
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
! uncaughtExceptionHandler = eh;
}
/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
--- 1999,2009 ----
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
! U.putReferenceRelease(this, UNCAUGHTEXCEPTIONHANDLER, eh);
}
/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
< prev index next >