summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/lang/management/ThreadInfo.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/lang/management/ThreadInfo.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/lang/management/ThreadInfo.java')
-rw-r--r--libjava/classpath/java/lang/management/ThreadInfo.java895
1 files changed, 895 insertions, 0 deletions
diff --git a/libjava/classpath/java/lang/management/ThreadInfo.java b/libjava/classpath/java/lang/management/ThreadInfo.java
new file mode 100644
index 000000000..a4ecc76f5
--- /dev/null
+++ b/libjava/classpath/java/lang/management/ThreadInfo.java
@@ -0,0 +1,895 @@
+/* ThreadInfo.java - Information on a thread
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath 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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.management;
+
+import java.util.Arrays;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+/**
+ * <p>
+ * A class which maintains information about a particular
+ * thread. This information includes:
+ * </p>
+ * <ul>
+ * <li><strong>General Thread Information:</strong>
+ * <ul>
+ * <li>The identifier of the thread.</li>
+ * <li>The name of the thread.</li>
+ * </ul>
+ * </li>
+ * <li><strong>Execution Information:</strong>
+ * <ul>
+ * <li>The current state of the thread (e.g. blocked, runnable)</li>
+ * <li>The object upon which the thread is blocked, either because
+ * the thread is waiting to obtain the monitor of that object to enter
+ * one of its synchronized monitor, or because
+ * {@link java.lang.Object#wait()} has been called while the thread
+ * was within a method of that object.</li>
+ * <li>The thread identifier of the current thread holding an object's
+ * monitor, upon which the thread described here is blocked.</li>
+ * <li>The stack trace of the thread (if requested on creation
+ * of this object</li>
+ * <li>The current locks held on object monitors by the thread.</li>
+ * <li>The current locks held on ownable synchronizers by the thread.</li>
+ * </ul>
+ * <li><strong>Synchronization Statistics</strong>
+ * <ul>
+ * <li>The number of times the thread has been blocked waiting for
+ * an object's monitor or in a {@link java.lang.Object#wait()} call.</li>
+ * <li>The accumulated time the thread has been blocked waiting for
+ * an object's monitor on in a {@link java.lang.Object#wait()} call.
+ * The availability of these statistics depends on the virtual machine's
+ * support for thread contention monitoring (see
+ * {@link ThreadMXBean#isThreadContentionMonitoringSupported()}.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ * @see ThreadMXBean#isThreadContentionMonitoringSupported()
+ */
+public class ThreadInfo
+{
+
+ /**
+ * The id of the thread which this instance concerns.
+ */
+ private long threadId;
+
+ /**
+ * The name of the thread which this instance concerns.
+ */
+ private String threadName;
+
+ /**
+ * The state of the thread which this instance concerns.
+ */
+ private Thread.State threadState;
+
+ /**
+ * The number of times the thread has been blocked.
+ */
+ private long blockedCount;
+
+ /**
+ * The accumulated number of milliseconds the thread has
+ * been blocked (used only with thread contention monitoring
+ * support).
+ */
+ private long blockedTime;
+
+ /**
+ * The name of the monitor lock on which this thread
+ * is blocked (if any).
+ */
+ private String lockName;
+
+ /**
+ * The id of the thread which owns the monitor lock on
+ * which this thread is blocked, or <code>-1</code>
+ * if there is no owner.
+ */
+ private long lockOwnerId;
+
+ /**
+ * The name of the thread which owns the monitor lock on
+ * which this thread is blocked, or <code>null</code>
+ * if there is no owner.
+ */
+ private String lockOwnerName;
+
+ /**
+ * The number of times the thread has been in a waiting
+ * state.
+ */
+ private long waitedCount;
+
+ /**
+ * The accumulated number of milliseconds the thread has
+ * been waiting (used only with thread contention monitoring
+ * support).
+ */
+ private long waitedTime;
+
+ /**
+ * True if the thread is in a native method.
+ */
+ private boolean isInNative;
+
+ /**
+ * True if the thread is suspended.
+ */
+ private boolean isSuspended;
+
+ /**
+ * The stack trace of the thread.
+ */
+ private StackTraceElement[] trace;
+
+ /**
+ * The array of information on monitors locked by the thread.
+ */
+ private MonitorInfo[] lockedMonitors;
+
+ /**
+ * The array of information on ownable synchronizers locked
+ * by the thread.
+ */
+ private LockInfo[] lockedSynchronizers;
+
+ /**
+ * Cache a local reference to the thread management bean.
+ */
+ private static ThreadMXBean bean = null;
+
+ /**
+ * Cache the {@link javax.management.openmbean.CompositeType}
+ * for the {@link StackTraceElement}.
+ */
+ private static CompositeType seType;
+
+ /**
+ * Constructs a new {@link ThreadInfo} corresponding
+ * to the thread details specified.
+ *
+ * @param threadId the id of the thread on which this
+ * new instance will be based.
+ * @param threadName the name of the thread on which
+ * this new instance will be based.
+ * @param threadState the state of the thread on which
+ * this new instance will be based.
+ * @param blockedCount the number of times the thread
+ * has been blocked.
+ * @param blockedTime the accumulated number of milliseconds
+ * the specified thread has been blocked
+ * (only used with contention monitoring enabled)
+ * @param lockName the name of the monitor lock the thread is waiting for
+ * (only used if blocked)
+ * @param lockOwnerId the id of the thread which owns the monitor
+ * lock, or <code>-1</code> if it doesn't have an owner
+ * (only used if blocked)
+ * @param lockOwnerName the name of the thread which owns the monitor
+ * lock, or <code>null</code> if it doesn't have an
+ * owner (only used if blocked)
+ * @param waitedCount the number of times the thread has been in a
+ * waiting state.
+ * @param waitedTime the accumulated number of milliseconds the
+ * specified thread has been waiting
+ * (only used with contention monitoring enabled)
+ * @param isInNative true if the thread is in a native method.
+ * @param isSuspended true if the thread is suspended.
+ * @param trace the stack trace of the thread to a pre-determined
+ * depth (see VMThreadMXBeanImpl)
+ * @param lockedMonitors an array of {@link MonitorInfo} objects
+ * representing locks held on object monitors
+ * by the thread.
+ * @param lockedSynchronizers an array of {@link LockInfo} objects
+ * representing locks held on ownable
+ * synchronizers by the thread.
+ *
+ * @since 1.6
+ */
+ private ThreadInfo(long threadId, String threadName, Thread.State threadState,
+ long blockedCount, long blockedTime, String lockName,
+ long lockOwnerId, String lockOwnerName, long waitedCount,
+ long waitedTime, boolean isInNative, boolean isSuspended,
+ StackTraceElement[] trace, MonitorInfo[] lockedMonitors,
+ LockInfo[] lockedSynchronizers)
+ {
+ this.threadId = threadId;
+ this.threadName = threadName;
+ this.threadState = threadState;
+ this.blockedCount = blockedCount;
+ this.blockedTime = blockedTime;
+ this.lockName = lockName;
+ this.lockOwnerId = lockOwnerId;
+ this.lockOwnerName = lockOwnerName;
+ this.waitedCount = waitedCount;
+ this.waitedTime = waitedTime;
+ this.isInNative = isInNative;
+ this.isSuspended = isSuspended;
+ this.trace = trace;
+ this.lockedMonitors = lockedMonitors;
+ this.lockedSynchronizers = lockedSynchronizers;
+ }
+
+ /**
+ * Checks for an attribute in a {@link CompositeData} structure
+ * with the correct type.
+ *
+ * @param ctype the composite data type to check.
+ * @param name the name of the attribute.
+ * @param type the type to check for.
+ * @throws IllegalArgumentException if the attribute is absent
+ * or of the wrong type.
+ */
+ static void checkAttribute(CompositeType ctype, String name,
+ OpenType type)
+ throws IllegalArgumentException
+ {
+ OpenType foundType = ctype.getType(name);
+ if (foundType == null)
+ throw new IllegalArgumentException("Could not find a field named " +
+ name);
+ if (!(foundType.equals(type)))
+ throw new IllegalArgumentException("Field " + name + " is not of " +
+ "type " + type.getClassName());
+ }
+
+ /**
+ * Returns the {@link javax.management.openmbean.CompositeType} for
+ * a {@link StackTraceElement}.
+ *
+ * @return the type for the stack trace element.
+ */
+ static CompositeType getStackTraceType()
+ {
+ if (seType == null)
+ try
+ {
+ seType = new CompositeType(StackTraceElement.class.getName(),
+ "An element of a stack trace",
+ new String[] { "className", "methodName",
+ "fileName", "lineNumber",
+ "nativeMethod"
+ },
+ new String[] { "Name of the class",
+ "Name of the method",
+ "Name of the source code file",
+ "Line number",
+ "True if this is a native method"
+ },
+ new OpenType[] {
+ SimpleType.STRING, SimpleType.STRING,
+ SimpleType.STRING, SimpleType.INTEGER,
+ SimpleType.BOOLEAN
+ });
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data type for the " +
+ "stack trace element.", e);
+ }
+ return seType;
+ }
+
+ /**
+ * <p>
+ * Returns a {@link ThreadInfo} instance using the values
+ * given in the supplied
+ * {@link javax.management.openmbean.CompositeData} object.
+ * The composite data instance should contain the following
+ * attributes with the specified types:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>threadId</td><td>java.lang.Long</td></tr>
+ * <tr><td>threadName</td><td>java.lang.String</td></tr>
+ * <tr><td>threadState</td><td>java.lang.String</td></tr>
+ * <tr><td>suspended</td><td>java.lang.Boolean</td></tr>
+ * <tr><td>inNative</td><td>java.lang.Boolean</td></tr>
+ * <tr><td>blockedCount</td><td>java.lang.Long</td></tr>
+ * <tr><td>blockedTime</td><td>java.lang.Long</td></tr>
+ * <tr><td>waitedCount</td><td>java.lang.Long</td></tr>
+ * <tr><td>waitedTime</td><td>java.lang.Long</td></tr>
+ * <tr><td>lockName</td><td>java.lang.String</td></tr>
+ * <tr><td>lockOwnerId</td><td>java.lang.Long</td></tr>
+ * <tr><td>lockOwnerName</td><td>java.lang.String</td></tr>
+ * <tr><td>stackTrace</td><td>javax.management.openmbean.CompositeData[]
+ * </td></tr>
+ * </table>
+ * <p>
+ * The stack trace is further described as:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>className</td><td>java.lang.String</td></tr>
+ * <tr><td>methodName</td><td>java.lang.String</td></tr>
+ * <tr><td>fileName</td><td>java.lang.String</td></tr>
+ * <tr><td>lineNumber</td><td>java.lang.Integer</td></tr>
+ * <tr><td>nativeMethod</td><td>java.lang.Boolean</td></tr>
+ * </table>
+ *
+ * @param data the composite data structure to take values from.
+ * @return a new instance containing the values from the
+ * composite data structure, or <code>null</code>
+ * if the data structure was also <code>null</code>.
+ * @throws IllegalArgumentException if the composite data structure
+ * does not match the structure
+ * outlined above.
+ */
+ public static ThreadInfo from(CompositeData data)
+ {
+ if (data == null)
+ return null;
+ CompositeType type = data.getCompositeType();
+ checkAttribute(type, "ThreadId", SimpleType.LONG);
+ checkAttribute(type, "ThreadName", SimpleType.STRING);
+ checkAttribute(type, "ThreadState", SimpleType.STRING);
+ checkAttribute(type, "Suspended", SimpleType.BOOLEAN);
+ checkAttribute(type, "InNative", SimpleType.BOOLEAN);
+ checkAttribute(type, "BlockedCount", SimpleType.LONG);
+ checkAttribute(type, "BlockedTime", SimpleType.LONG);
+ checkAttribute(type, "WaitedCount", SimpleType.LONG);
+ checkAttribute(type, "WaitedTime", SimpleType.LONG);
+ checkAttribute(type, "LockName", SimpleType.STRING);
+ checkAttribute(type, "LockOwnerId", SimpleType.LONG);
+ checkAttribute(type, "LockOwnerName", SimpleType.STRING);
+ try
+ {
+ checkAttribute(type, "StackTrace",
+ new ArrayType(1, getStackTraceType()));
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the array for the stack trace element.",
+ e);
+ }
+ OpenType foundType = type.getType("LockedMonitors");
+ if (foundType != null)
+ try
+ {
+ CompositeType mType = new CompositeType(MonitorInfo.class.getName(),
+ "Information on a object monitor lock",
+ new String[] { "ClassName",
+ "IdentityHashCode",
+ "LockedStackDepth",
+ "LockedStackFrame"
+ },
+ new String[] { "Name of the class",
+ "Identity hash code " +
+ "of the class",
+ "Stack depth at time " +
+ "of lock",
+ "Stack frame at time " +
+ "of lock",
+ },
+ new OpenType[] {
+ SimpleType.STRING, SimpleType.INTEGER,
+ SimpleType.INTEGER, getStackTraceType()
+ });
+ if (!(foundType.equals(new ArrayType(1, mType))))
+ throw new IllegalArgumentException("Field LockedMonitors is not of " +
+ "type " + mType.getClassName());
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data type for the " +
+ "object monitor information array.", e);
+ }
+ foundType = type.getType("LockedSynchronizers");
+ if (foundType != null)
+ try
+ {
+ CompositeType lType = new CompositeType(LockInfo.class.getName(),
+ "Information on a lock",
+ new String[] { "ClassName",
+ "IdentityHashCode"
+ },
+ new String[] { "Name of the class",
+ "Identity hash code " +
+ "of the class"
+ },
+ new OpenType[] {
+ SimpleType.STRING, SimpleType.INTEGER
+ });
+ if (!(foundType.equals(new ArrayType(1, lType))))
+ throw new IllegalArgumentException("Field LockedSynchronizers is not of " +
+ "type " + lType.getClassName());
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data type for the " +
+ "ownable synchronizerinformation array.", e);
+ }
+ CompositeData[] dTraces = (CompositeData[]) data.get("StackTrace");
+ StackTraceElement[] traces = new StackTraceElement[dTraces.length];
+ for (int a = 0; a < dTraces.length; ++a)
+ /* FIXME: We can't use the boolean as there is no available
+ constructor. */
+ traces[a] =
+ new StackTraceElement((String) dTraces[a].get("ClassName"),
+ (String) dTraces[a].get("MethodName"),
+ (String) dTraces[a].get("FileName"),
+ ((Integer)
+ dTraces[a].get("LineNumber")).intValue());
+ MonitorInfo[] mInfo;
+ if (data.containsKey("LockedMonitors"))
+ {
+ CompositeData[] dmInfos = (CompositeData[]) data.get("LockedMonitors");
+ mInfo = new MonitorInfo[dmInfos.length];
+ for (int a = 0; a < dmInfos.length; ++a)
+ mInfo[a] = MonitorInfo.from(dmInfos[a]);
+ }
+ else
+ mInfo = new MonitorInfo[]{};
+ LockInfo[] lInfo;
+ if (data.containsKey("LockedSynchronizers"))
+ {
+ CompositeData[] dlInfos = (CompositeData[]) data.get("LockedSynchronizers");
+ lInfo = new LockInfo[dlInfos.length];
+ for (int a = 0; a < dlInfos.length; ++a)
+ lInfo[a] = new LockInfo((String) dlInfos[a].get("ClassName"),
+ (Integer) dlInfos[a].get("IdentityHashCode"));
+ }
+ else
+ lInfo = new LockInfo[]{};
+ return new ThreadInfo(((Long) data.get("ThreadId")).longValue(),
+ (String) data.get("ThreadName"),
+ Thread.State.valueOf((String) data.get("ThreadState")),
+ ((Long) data.get("BlockedCount")).longValue(),
+ ((Long) data.get("BlockedTime")).longValue(),
+ (String) data.get("LockName"),
+ ((Long) data.get("LockOwnerId")).longValue(),
+ (String) data.get("LockOwnerName"),
+ ((Long) data.get("WaitedCount")).longValue(),
+ ((Long) data.get("WaitedTime")).longValue(),
+ ((Boolean) data.get("InNative")).booleanValue(),
+ ((Boolean) data.get("Suspended")).booleanValue(),
+ traces, mInfo, lInfo);
+ }
+
+ /**
+ * Returns the number of times this thread has been
+ * in the {@link java.lang.Thread.State#BLOCKED} state.
+ * A thread enters this state when it is waiting to
+ * obtain an object's monitor. This may occur either
+ * on entering a synchronized method for the first time,
+ * or on re-entering it following a call to
+ * {@link java.lang.Object#wait()}.
+ *
+ * @return the number of times this thread has been blocked.
+ */
+ public long getBlockedCount()
+ {
+ return blockedCount;
+ }
+
+ /**
+ * <p>
+ * Returns the accumulated number of milliseconds this
+ * thread has been in the
+ * {@link java.lang.Thread.State#BLOCKED} state
+ * since thread contention monitoring was last enabled.
+ * A thread enters this state when it is waiting to
+ * obtain an object's monitor. This may occur either
+ * on entering a synchronized method for the first time,
+ * or on re-entering it following a call to
+ * {@link java.lang.Object#wait()}.
+ * </p>
+ * <p>
+ * Use of this method requires virtual machine support
+ * for thread contention monitoring and for this support
+ * to be enabled.
+ * </p>
+ *
+ * @return the accumulated time (in milliseconds) that this
+ * thread has spent in the blocked state, since
+ * thread contention monitoring was enabled, or -1
+ * if thread contention monitoring is disabled.
+ * @throws UnsupportedOperationException if the virtual
+ * machine does not
+ * support contention
+ * monitoring.
+ * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
+ * @see ThreadMXBean#isThreadContentionMonitoringSupported()
+ */
+ public long getBlockedTime()
+ {
+ if (bean == null)
+ bean = ManagementFactory.getThreadMXBean();
+ // Will throw UnsupportedOperationException for us
+ if (bean.isThreadContentionMonitoringEnabled())
+ return blockedTime;
+ else
+ return -1;
+ }
+
+ /**
+ * Returns an array of {@link MonitorInfo} objects representing
+ * information on the locks on object monitors held by the thread.
+ * If no locks are held, or such information was not requested
+ * on creating this {@link ThreadInfo} object, a zero-length
+ * array will be returned.
+ *
+ * @return information on object monitors locked by this thread.
+ */
+ public MonitorInfo[] getLockedMonitors()
+ {
+ return lockedMonitors;
+ }
+
+ /**
+ * Returns an array of {@link LockInfo} objects representing
+ * information on the locks on ownable synchronizers held by the thread.
+ * If no locks are held, or such information was not requested
+ * on creating this {@link ThreadInfo} object, a zero-length
+ * array will be returned.
+ *
+ * @return information on ownable synchronizers locked by this thread.
+ */
+ public LockInfo[] getLockedSynchronizers()
+ {
+ return lockedSynchronizers;
+ }
+
+ /**
+ * <p>
+ * Returns a {@link LockInfo} object representing the
+ * lock on which this thread is blocked. If the thread
+ * is not blocked, this method returns <code>null</code>.
+ * </p>
+ * <p>
+ * The thread may be blocked due to one of three reasons:
+ * </p>
+ * <ol>
+ * <li>The thread is in the <code>BLOCKED</code> state
+ * waiting to acquire an object monitor in order to enter
+ * a synchronized method or block.</li>
+ * <li>The thread is in the <code>WAITING</code> or
+ * <code>TIMED_WAITING</code> state due to a call to
+ * {@link java.lang.Object#wait()}.</li>
+ * <li>The thread is in the <code>WAITING</code> or
+ * <code>TIMED_WAITING</code> state due to a call
+ * to {@link java.util.concurrent.locks.LockSupport#park()}.
+ * The lock is the return value of
+ * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li>
+ * </ol>
+ *
+ * @return a {@link LockInfo} object representing the lock on
+ * which the thread is blocked, or <code>null</code> if
+ * the thread isn't blocked.
+ * @since 1.6
+ * @see #getLockName()
+ */
+ public LockInfo getLockInfo()
+ {
+ String lockName = getLockName();
+ int at = lockName.indexOf('@');
+ return new LockInfo(lockName.substring(0, at),
+ Integer.decode(lockName.substring(at + 1)));
+ }
+
+ /**
+ * <p>
+ * Returns a {@link java.lang.String} representation of
+ * the lock on which this thread is blocked. If
+ * the thread is not blocked, this method returns
+ * <code>null</code>.
+ * </p>
+ * <p>
+ * The returned {@link java.lang.String} is constructed
+ * using the class name and identity hashcode (usually
+ * the memory address of the object) of the lock. The
+ * two are separated by the '@' character, and the identity
+ * hashcode is represented in hexadecimal. Thus, for a
+ * lock, <code>l</code>, the returned value is
+ * the result of concatenating
+ * <code>l.getClass().getName()</code>, <code>"@"</code>
+ * and
+ * <code>Integer.toHexString(System.identityHashCode(l))</code>.
+ * The value is only unique to the extent that the identity
+ * hash code is also unique. The value is the same as would
+ * be returned by <code>getLockInfo().toString()</code>
+ * </p>
+ *
+ * @return a string representing the lock on which this
+ * thread is blocked, or <code>null</code> if
+ * the thread is not blocked.
+ */
+ public String getLockName()
+ {
+ if (!isThreadBlocked())
+ return null;
+ return lockName;
+ }
+
+ /**
+ * Returns the identifier of the thread which owns the
+ * monitor lock this thread is waiting for. -1 is returned
+ * if either this thread is not blocked, or the lock is
+ * not held by any other thread.
+ *
+ * @return the thread identifier of thread holding the lock
+ * this thread is waiting for, or -1 if the thread
+ * is not blocked or the lock is not held by another
+ * thread.
+ */
+ public long getLockOwnerId()
+ {
+ if (!isThreadBlocked())
+ return -1;
+ return lockOwnerId;
+ }
+
+ /**
+ * Returns the name of the thread which owns the
+ * monitor lock this thread is waiting for. <code>null</code>
+ * is returned if either this thread is not blocked,
+ * or the lock is not held by any other thread.
+ *
+ * @return the thread identifier of thread holding the lock
+ * this thread is waiting for, or <code>null</code>
+ * if the thread is not blocked or the lock is not
+ * held by another thread.
+ */
+ public String getLockOwnerName()
+ {
+ if (!isThreadBlocked())
+ return null;
+ return lockOwnerName;
+ }
+
+ /**
+ * <p>
+ * Returns the stack trace of this thread to the depth
+ * specified on creation of this {@link ThreadInfo}
+ * object. If the depth is zero, an empty array will
+ * be returned. For non-zero arrays, the elements
+ * start with the most recent trace at position zero.
+ * The bottom of the stack represents the oldest method
+ * invocation which meets the depth requirements.
+ * </p>
+ * <p>
+ * Some virtual machines may not be able to return
+ * stack trace information for a thread. In these
+ * cases, an empty array will also be returned.
+ * </p>
+ *
+ * @return an array of {@link java.lang.StackTraceElement}s
+ * representing the trace of this thread.
+ */
+ public StackTraceElement[] getStackTrace()
+ {
+ return trace;
+ }
+
+ /**
+ * Returns the identifier of the thread associated with
+ * this instance of {@link ThreadInfo}.
+ *
+ * @return the thread's identifier.
+ */
+ public long getThreadId()
+ {
+ return threadId;
+ }
+
+ /**
+ * Returns the name of the thread associated with
+ * this instance of {@link ThreadInfo}.
+ *
+ * @return the thread's name.
+ */
+ public String getThreadName()
+ {
+ return threadName;
+ }
+
+ /**
+ * Returns the state of the thread associated with
+ * this instance of {@link ThreadInfo}.
+ *
+ * @return the thread's state.
+ */
+ public Thread.State getThreadState()
+ {
+ return threadState;
+ }
+
+ /**
+ * Returns the number of times this thread has been
+ * in the {@link java.lang.Thread.State#WAITING}
+ * or {@link java.lang.Thread.State#TIMED_WAITING} state.
+ * A thread enters one of these states when it is waiting
+ * due to a call to {@link java.lang.Object.wait()},
+ * {@link java.lang.Object.join()} or
+ * {@link java.lang.concurrent.locks.LockSupport.park()},
+ * either with an infinite or timed delay, respectively.
+ *
+ * @return the number of times this thread has been waiting.
+ */
+ public long getWaitedCount()
+ {
+ return waitedCount;
+ }
+
+ /**
+ * <p>
+ * Returns the accumulated number of milliseconds this
+ * thread has been in the
+ * {@link java.lang.Thread.State#WAITING} or
+ * {@link java.lang.Thread.State#TIMED_WAITING} state,
+ * since thread contention monitoring was last enabled.
+ * A thread enters one of these states when it is waiting
+ * due to a call to {@link java.lang.Object.wait()},
+ * {@link java.lang.Object.join()} or
+ * {@link java.lang.concurrent.locks.LockSupport.park()},
+ * either with an infinite or timed delay, respectively.
+ * </p>
+ * <p>
+ * Use of this method requires virtual machine support
+ * for thread contention monitoring and for this support
+ * to be enabled.
+ * </p>
+ *
+ * @return the accumulated time (in milliseconds) that this
+ * thread has spent in one of the waiting states, since
+ * thread contention monitoring was enabled, or -1
+ * if thread contention monitoring is disabled.
+ * @throws UnsupportedOperationException if the virtual
+ * machine does not
+ * support contention
+ * monitoring.
+ * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
+ * @see ThreadMXBean#isThreadContentionMonitoringSupported()
+ */
+ public long getWaitedTime()
+ {
+ if (bean == null)
+ bean = ManagementFactory.getThreadMXBean();
+ // Will throw UnsupportedOperationException for us
+ if (bean.isThreadContentionMonitoringEnabled())
+ return waitedTime;
+ else
+ return -1;
+ }
+
+ /**
+ * Returns true if the thread is in a native method. This
+ * excludes native code which forms part of the virtual
+ * machine itself, or which results from Just-In-Time
+ * compilation.
+ *
+ * @return true if the thread is in a native method, false
+ * otherwise.
+ */
+ public boolean isInNative()
+ {
+ return isInNative;
+ }
+
+ /**
+ * Returns true if the thread has been suspended using
+ * {@link java.lang.Thread#suspend()}.
+ *
+ * @return true if the thread is suspended, false otherwise.
+ */
+ public boolean isSuspended()
+ {
+ return isSuspended;
+ }
+
+ /**
+ * Returns a {@link java.lang.String} representation of
+ * this {@link ThreadInfo} object. This takes the form
+ * <code>java.lang.management.ThreadInfo[id=tid, name=n,
+ * state=s, blockedCount=bc, waitedCount=wc, isInNative=iin,
+ * isSuspended=is]</code>, where <code>tid</code> is
+ * the thread identifier, <code>n</code> is the
+ * thread name, <code>s</code> is the thread state,
+ * <code>bc</code> is the blocked state count,
+ * <code>wc</code> is the waiting state count and
+ * <code>iin</code> and <code>is</code> are boolean
+ * flags to indicate the thread is in native code or
+ * suspended respectively. If the thread is blocked,
+ * <code>lock=l, lockOwner=lo</code> is also included,
+ * where <code>l</code> is the lock waited for, and
+ * <code>lo</code> is the thread which owns the lock
+ * (or null if there is no owner).
+ *
+ * @return the string specified above.
+ */
+ public String toString()
+ {
+ return getClass().getName() +
+ "[id=" + threadId +
+ ", name=" + threadName +
+ ", state=" + threadState +
+ ", blockedCount=" + blockedCount +
+ ", waitedCount=" + waitedCount +
+ ", isInNative=" + isInNative +
+ ", isSuspended=" + isSuspended +
+ (isThreadBlocked() ?
+ ", lockOwnerId=" + lockOwnerId +
+ ", lockOwnerName=" + lockOwnerName : "") +
+ ", lockedMonitors=" + Arrays.toString(lockedMonitors) +
+ ", lockedSynchronizers=" + Arrays.toString(lockedSynchronizers) +
+ "]";
+ }
+
+ /**
+ * <p>
+ * Returns true if the thread is in a blocked state.
+ * The thread is regarded as blocked if:
+ * </p>
+ * <ol>
+ * <li>The thread is in the <code>BLOCKED</code> state
+ * waiting to acquire an object monitor in order to enter
+ * a synchronized method or block.</li>
+ * <li>The thread is in the <code>WAITING</code> or
+ * <code>TIMED_WAITING</code> state due to a call to
+ * {@link java.lang.Object#wait()}.</li>
+ * <li>The thread is in the <code>WAITING</code> or
+ * <code>TIMED_WAITING</code> state due to a call
+ * to {@link java.util.concurrent.locks.LockSupport#park()}.
+ * The lock is the return value of
+ * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li>
+ * </ol>
+ *
+ * @return true if the thread is blocked.
+ */
+ private boolean isThreadBlocked()
+ {
+ return (threadState == Thread.State.BLOCKED ||
+ threadState == Thread.State.WAITING ||
+ threadState == Thread.State.TIMED_WAITING);
+ }
+
+}