/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang.management;
import javax.management.openmbean.
CompositeData;
import sun.management.
ManagementFactoryHelper;
import sun.management.
ThreadInfoCompositeData;
import static java.lang.
Thread.
State.*;
/**
* Thread information. <tt>ThreadInfo</tt> contains the information
* about a thread including:
* <h3>General thread information</h3>
* <ul>
* <li>Thread ID.</li>
* <li>Name of the thread.</li>
* </ul>
*
* <h3>Execution information</h3>
* <ul>
* <li>Thread state.</li>
* <li>The object upon which the thread is blocked due to:
* <ul>
* <li>waiting to enter a synchronization block/method, or</li>
* <li>waiting to be notified in a {@link Object#wait Object.wait} method,
* or</li>
* <li>parking due to a {@link java.util.concurrent.locks.LockSupport#park
* LockSupport.park} call.</li>
* </ul>
* </li>
* <li>The ID of the thread that owns the object
* that the thread is blocked.</li>
* <li>Stack trace of the thread.</li>
* <li>List of object monitors locked by the thread.</li>
* <li>List of <a href="LockInfo.html#OwnableSynchronizer">
* ownable synchronizers</a> locked by the thread.</li>
* </ul>
*
* <h4><a name="SyncStats">Synchronization Statistics</a></h4>
* <ul>
* <li>The number of times that the thread has blocked for
* synchronization or waited for notification.</li>
* <li>The accumulated elapsed time that the thread has blocked
* for synchronization or waited for notification
* since {@link ThreadMXBean#setThreadContentionMonitoringEnabled
* thread contention monitoring}
* was enabled. Some Java virtual machine implementation
* may not support this. The
* {@link ThreadMXBean#isThreadContentionMonitoringSupported()}
* method can be used to determine if a Java virtual machine
* supports this.</li>
* </ul>
*
* <p>This thread information class is designed for use in monitoring of
* the system, not for synchronization control.
*
* <h4>MXBean Mapping</h4>
* <tt>ThreadInfo</tt> is mapped to a {@link CompositeData CompositeData}
* with attributes as specified in
* the {@link #from from} method.
*
* @see ThreadMXBean#getThreadInfo
* @see ThreadMXBean#dumpAllThreads
*
* @author Mandy Chung
* @since 1.5
*/
public class
ThreadInfo {
private
String threadName;
private long
threadId;
private long
blockedTime;
private long
blockedCount;
private long
waitedTime;
private long
waitedCount;
private
LockInfo lock;
private
String lockName;
private long
lockOwnerId;
private
String lockOwnerName;
private boolean
inNative;
private boolean
suspended;
private
Thread.
State threadState;
private
StackTraceElement[]
stackTrace;
private
MonitorInfo[]
lockedMonitors;
private
LockInfo[]
lockedSynchronizers;
private static
MonitorInfo[]
EMPTY_MONITORS = new
MonitorInfo[0];
private static
LockInfo[]
EMPTY_SYNCS = new
LockInfo[0];
/**
* Constructor of ThreadInfo created by the JVM
*
* @param t Thread
* @param state Thread state
* @param lockObj Object on which the thread is blocked
* @param lockOwner the thread holding the lock
* @param blockedCount Number of times blocked to enter a lock
* @param blockedTime Approx time blocked to enter a lock
* @param waitedCount Number of times waited on a lock
* @param waitedTime Approx time waited on a lock
* @param stackTrace Thread stack trace
*/
private
ThreadInfo(
Thread t, int
state,
Object lockObj,
Thread lockOwner,
long
blockedCount, long
blockedTime,
long
waitedCount, long
waitedTime,
StackTraceElement[]
stackTrace) {
initialize(
t,
state,
lockObj,
lockOwner,
blockedCount,
blockedTime,
waitedCount,
waitedTime,
stackTrace,
EMPTY_MONITORS,
EMPTY_SYNCS);
}
/**
* Constructor of ThreadInfo created by the JVM
* for {@link ThreadMXBean#getThreadInfo(long[],boolean,boolean)}
* and {@link ThreadMXBean#dumpAllThreads}
*
* @param t Thread
* @param state Thread state
* @param lockObj Object on which the thread is blocked
* @param lockOwner the thread holding the lock
* @param blockedCount Number of times blocked to enter a lock
* @param blockedTime Approx time blocked to enter a lock
* @param waitedCount Number of times waited on a lock
* @param waitedTime Approx time waited on a lock
* @param stackTrace Thread stack trace
* @param monitors List of locked monitors
* @param stackDepths List of stack depths
* @param synchronizers List of locked synchronizers
*/
private
ThreadInfo(
Thread t, int
state,
Object lockObj,
Thread lockOwner,
long
blockedCount, long
blockedTime,
long
waitedCount, long
waitedTime,
StackTraceElement[]
stackTrace,
Object[]
monitors,
int[]
stackDepths,
Object[]
synchronizers) {
int
numMonitors = (
monitors == null ? 0 :
monitors.length);
MonitorInfo[]
lockedMonitors;
if (
numMonitors == 0) {
lockedMonitors =
EMPTY_MONITORS;
} else {
lockedMonitors = new
MonitorInfo[
numMonitors];
for (int
i = 0;
i <
numMonitors;
i++) {
Object lock =
monitors[
i];
String className =
lock.
getClass().
getName();
int
identityHashCode =
System.
identityHashCode(
lock);
int
depth =
stackDepths[
i];
StackTraceElement ste = (
depth >= 0 ?
stackTrace[
depth]
: null);
lockedMonitors[
i] = new
MonitorInfo(
className,
identityHashCode,
depth,
ste);
}
}
int
numSyncs = (
synchronizers == null ? 0 :
synchronizers.length);
LockInfo[]
lockedSynchronizers;
if (
numSyncs == 0) {
lockedSynchronizers =
EMPTY_SYNCS;
} else {
lockedSynchronizers = new
LockInfo[
numSyncs];
for (int
i = 0;
i <
numSyncs;
i++) {
Object lock =
synchronizers[
i];
String className =
lock.
getClass().
getName();
int
identityHashCode =
System.
identityHashCode(
lock);
lockedSynchronizers[
i] = new
LockInfo(
className,
identityHashCode);
}
}
initialize(
t,
state,
lockObj,
lockOwner,
blockedCount,
blockedTime,
waitedCount,
waitedTime,
stackTrace,
lockedMonitors,
lockedSynchronizers);
}
/**
* Initialize ThreadInfo object
*
* @param t Thread
* @param state Thread state
* @param lockObj Object on which the thread is blocked
* @param lockOwner the thread holding the lock
* @param blockedCount Number of times blocked to enter a lock
* @param blockedTime Approx time blocked to enter a lock
* @param waitedCount Number of times waited on a lock
* @param waitedTime Approx time waited on a lock
* @param stackTrace Thread stack trace
* @param lockedMonitors List of locked monitors
* @param lockedSynchronizers List of locked synchronizers
*/
private void
initialize(
Thread t, int
state,
Object lockObj,
Thread lockOwner,
long
blockedCount, long
blockedTime,
long
waitedCount, long
waitedTime,
StackTraceElement[]
stackTrace,
MonitorInfo[]
lockedMonitors,
LockInfo[]
lockedSynchronizers) {
this.
threadId =
t.
getId();
this.
threadName =
t.
getName();
this.
threadState =
ManagementFactoryHelper.
toThreadState(
state);
this.
suspended =
ManagementFactoryHelper.
isThreadSuspended(
state);
this.
inNative =
ManagementFactoryHelper.
isThreadRunningNative(
state);
this.
blockedCount =
blockedCount;
this.
blockedTime =
blockedTime;
this.
waitedCount =
waitedCount;
this.
waitedTime =
waitedTime;
if (
lockObj == null) {
this.
lock = null;
this.
lockName = null;
} else {
this.
lock = new
LockInfo(
lockObj);
this.
lockName =
lock.
getClassName() + '@' +
Integer.
toHexString(
lock.
getIdentityHashCode());
}
if (
lockOwner == null) {
this.
lockOwnerId = -1;
this.
lockOwnerName = null;
} else {
this.
lockOwnerId =
lockOwner.
getId();
this.
lockOwnerName =
lockOwner.
getName();
}
if (
stackTrace == null) {
this.
stackTrace =
NO_STACK_TRACE;
} else {
this.
stackTrace =
stackTrace;
}
this.
lockedMonitors =
lockedMonitors;
this.
lockedSynchronizers =
lockedSynchronizers;
}
/*
* Constructs a <tt>ThreadInfo</tt> object from a
* {@link CompositeData CompositeData}.
*/
private
ThreadInfo(
CompositeData cd) {
ThreadInfoCompositeData ticd =
ThreadInfoCompositeData.
getInstance(
cd);
threadId =
ticd.
threadId();
threadName =
ticd.
threadName();
blockedTime =
ticd.
blockedTime();
blockedCount =
ticd.
blockedCount();
waitedTime =
ticd.
waitedTime();
waitedCount =
ticd.
waitedCount();
lockName =
ticd.
lockName();
lockOwnerId =
ticd.
lockOwnerId();
lockOwnerName =
ticd.
lockOwnerName();
threadState =
ticd.
threadState();
suspended =
ticd.
suspended();
inNative =
ticd.
inNative();
stackTrace =
ticd.
stackTrace();
// 6.0 attributes
if (
ticd.
isCurrentVersion()) {
lock =
ticd.
lockInfo();
lockedMonitors =
ticd.
lockedMonitors();
lockedSynchronizers =
ticd.
lockedSynchronizers();
} else {
// lockInfo is a new attribute added in 1.6 ThreadInfo
// If cd is a 5.0 version, construct the LockInfo object
// from the lockName value.
if (
lockName != null) {
String result[] =
lockName.
split("@");
if (
result.length == 2) {
int
identityHashCode =
Integer.
parseInt(
result[1], 16);
lock = new
LockInfo(
result[0],
identityHashCode);
} else {
assert
result.length == 2;
lock = null;
}
} else {
lock = null;
}
lockedMonitors =
EMPTY_MONITORS;
lockedSynchronizers =
EMPTY_SYNCS;
}
}
/**
* Returns the ID of the thread associated with this <tt>ThreadInfo</tt>.
*
* @return the ID of the associated thread.
*/
public long
getThreadId() {
return
threadId;
}
/**
* Returns the name of the thread associated with this <tt>ThreadInfo</tt>.
*
* @return the name of the associated thread.
*/
public
String getThreadName() {
return
threadName;
}
/**
* Returns the state of the thread associated with this <tt>ThreadInfo</tt>.
*
* @return <tt>Thread.State</tt> of the associated thread.
*/
public
Thread.
State getThreadState() {
return
threadState;
}
/**
* Returns the approximate accumulated elapsed time (in milliseconds)
* that the thread associated with this <tt>ThreadInfo</tt>
* has blocked to enter or reenter a monitor
* since thread contention monitoring is enabled.
* I.e. the total accumulated time the thread has been in the
* {@link java.lang.Thread.State#BLOCKED BLOCKED} state since thread
* contention monitoring was last enabled.
* This method returns <tt>-1</tt> if thread contention monitoring
* is disabled.
*
* <p>The Java virtual machine may measure the time with a high
* resolution timer. This statistic is reset when
* the thread contention monitoring is reenabled.
*
* @return the approximate accumulated elapsed time in milliseconds
* that a thread entered the <tt>BLOCKED</tt> state;
* <tt>-1</tt> if thread contention monitoring is disabled.
*
* @throws java.lang.UnsupportedOperationException if the Java
* virtual machine does not support this operation.
*
* @see ThreadMXBean#isThreadContentionMonitoringSupported
* @see ThreadMXBean#setThreadContentionMonitoringEnabled
*/
public long
getBlockedTime() {
return
blockedTime;
}
/**
* Returns the total number of times that
* the thread associated with this <tt>ThreadInfo</tt>
* blocked to enter or reenter a monitor.
* I.e. the number of times a thread has been in the
* {@link java.lang.Thread.State#BLOCKED BLOCKED} state.
*
* @return the total number of times that the thread
* entered the <tt>BLOCKED</tt> state.
*/
public long
getBlockedCount() {
return
blockedCount;
}
/**
* Returns the approximate accumulated elapsed time (in milliseconds)
* that the thread associated with this <tt>ThreadInfo</tt>
* has waited for notification
* since thread contention monitoring is enabled.
* I.e. the total accumulated time the thread has been in the
* {@link java.lang.Thread.State#WAITING WAITING}
* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state
* since thread contention monitoring is enabled.
* This method returns <tt>-1</tt> if thread contention monitoring
* is disabled.
*
* <p>The Java virtual machine may measure the time with a high
* resolution timer. This statistic is reset when
* the thread contention monitoring is reenabled.
*
* @return the approximate accumulated elapsed time in milliseconds
* that a thread has been in the <tt>WAITING</tt> or
* <tt>TIMED_WAITING</tt> state;
* <tt>-1</tt> if thread contention monitoring is disabled.
*
* @throws java.lang.UnsupportedOperationException if the Java
* virtual machine does not support this operation.
*
* @see ThreadMXBean#isThreadContentionMonitoringSupported
* @see ThreadMXBean#setThreadContentionMonitoringEnabled
*/
public long
getWaitedTime() {
return
waitedTime;
}
/**
* Returns the total number of times that
* the thread associated with this <tt>ThreadInfo</tt>
* waited for notification.
* I.e. the number of times that a thread has been
* in the {@link java.lang.Thread.State#WAITING WAITING}
* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state.
*
* @return the total number of times that the thread
* was in the <tt>WAITING</tt> or <tt>TIMED_WAITING</tt> state.
*/
public long
getWaitedCount() {
return
waitedCount;
}
/**
* Returns the <tt>LockInfo</tt> of an object for which
* the thread associated with this <tt>ThreadInfo</tt>
* is blocked waiting.
* A thread can be blocked waiting for one of the following:
* <ul>
* <li>an object monitor to be acquired for entering or reentering
* a synchronization block/method.
* <br>The thread is in the {@link java.lang.Thread.State#BLOCKED BLOCKED}
* state waiting to enter the <tt>synchronized</tt> statement
* or method.
* <p></li>
* <li>an object monitor to be notified by another thread.
* <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING}
* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state
* due to a call to the {@link Object#wait Object.wait} method.
* <p></li>
* <li>a synchronization object responsible for the thread parking.
* <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING}
* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state
* due to a call to the
* {@link java.util.concurrent.locks.LockSupport#park(Object)
* LockSupport.park} method. The synchronization object
* is the object returned from
* {@link java.util.concurrent.locks.LockSupport#getBlocker
* LockSupport.getBlocker} method. Typically it is an
* <a href="LockInfo.html#OwnableSynchronizer"> ownable synchronizer</a>
* or a {@link java.util.concurrent.locks.Condition Condition}.</li>
* </ul>
*
* <p>This method returns <tt>null</tt> if the thread is not in any of
* the above conditions.
*
* @return <tt>LockInfo</tt> of an object for which the thread
* is blocked waiting if any; <tt>null</tt> otherwise.
* @since 1.6
*/
public
LockInfo getLockInfo() {
return
lock;
}
/**
* Returns the {@link LockInfo#toString string representation}
* of an object for which the thread associated with this
* <tt>ThreadInfo</tt> is blocked waiting.
* This method is equivalent to calling:
* <blockquote>
* <pre>
* getLockInfo().toString()
* </pre></blockquote>
*
* <p>This method will return <tt>null</tt> if this thread is not blocked
* waiting for any object or if the object is not owned by any thread.
*
* @return the string representation of the object on which
* the thread is blocked if any;
* <tt>null</tt> otherwise.
*
* @see #getLockInfo
*/
public
String getLockName() {
return
lockName;
}
/**
* Returns the ID of the thread which owns the object
* for which the thread associated with this <tt>ThreadInfo</tt>
* is blocked waiting.
* This method will return <tt>-1</tt> if this thread is not blocked
* waiting for any object or if the object is not owned by any thread.
*
* @return the thread ID of the owner thread of the object
* this thread is blocked on;
* <tt>-1</tt> if this thread is not blocked
* or if the object is not owned by any thread.
*
* @see #getLockInfo
*/
public long
getLockOwnerId() {
return
lockOwnerId;
}
/**
* Returns the name of the thread which owns the object
* for which the thread associated with this <tt>ThreadInfo</tt>
* is blocked waiting.
* This method will return <tt>null</tt> if this thread is not blocked
* waiting for any object or if the object is not owned by any thread.
*
* @return the name of the thread that owns the object
* this thread is blocked on;
* <tt>null</tt> if this thread is not blocked
* or if the object is not owned by any thread.
*
* @see #getLockInfo
*/
public
String getLockOwnerName() {
return
lockOwnerName;
}
/**
* Returns the stack trace of the thread
* associated with this <tt>ThreadInfo</tt>.
* If no stack trace was requested for this thread info, this method
* will return a zero-length array.
* If the returned array is of non-zero length then the first element of
* the array represents the top of the stack, which is the most recent
* method invocation in the sequence. The last element of the array
* represents the bottom of the stack, which is the least recent method
* invocation in the sequence.
*
* <p>Some Java virtual machines may, under some circumstances, omit one
* or more stack frames from the stack trace. In the extreme case,
* a virtual machine that has no stack trace information concerning
* the thread associated with this <tt>ThreadInfo</tt>
* is permitted to return a zero-length array from this method.
*
* @return an array of <tt>StackTraceElement</tt> objects of the thread.
*/
public
StackTraceElement[]
getStackTrace() {
return
stackTrace;
}
/**
* Tests if the thread associated with this <tt>ThreadInfo</tt>
* is suspended. This method returns <tt>true</tt> if
* {@link Thread#suspend} has been called.
*
* @return <tt>true</tt> if the thread is suspended;
* <tt>false</tt> otherwise.
*/
public boolean
isSuspended() {
return
suspended;
}
/**
* Tests if the thread associated with this <tt>ThreadInfo</tt>
* is executing native code via the Java Native Interface (JNI).
* The JNI native code does not include
* the virtual machine support code or the compiled native
* code generated by the virtual machine.
*
* @return <tt>true</tt> if the thread is executing native code;
* <tt>false</tt> otherwise.
*/
public boolean
isInNative() {
return
inNative;
}
/**
* Returns a string representation of this thread info.
* The format of this string depends on the implementation.
* The returned string will typically include
* the {@linkplain #getThreadName thread name},
* the {@linkplain #getThreadId thread ID},
* its {@linkplain #getThreadState state},
* and a {@linkplain #getStackTrace stack trace} if any.
*
* @return a string representation of this thread info.
*/
public
String toString() {
StringBuilder sb = new
StringBuilder("\"" +
getThreadName() + "\"" +
" Id=" +
getThreadId() + " " +
getThreadState());
if (
getLockName() != null) {
sb.
append(" on " +
getLockName());
}
if (
getLockOwnerName() != null) {
sb.
append(" owned by \"" +
getLockOwnerName() +
"\" Id=" +
getLockOwnerId());
}
if (
isSuspended()) {
sb.
append(" (suspended)");
}
if (
isInNative()) {
sb.
append(" (in native)");
}
sb.
append('\n');
int
i = 0;
for (;
i <
stackTrace.length &&
i <
MAX_FRAMES;
i++) {
StackTraceElement ste =
stackTrace[
i];
sb.
append("\tat " +
ste.
toString());
sb.
append('\n');
if (
i == 0 &&
getLockInfo() != null) {
Thread.
State ts =
getThreadState();
switch (
ts) {
case
BLOCKED:
sb.
append("\t- blocked on " +
getLockInfo());
sb.
append('\n');
break;
case
WAITING:
sb.
append("\t- waiting on " +
getLockInfo());
sb.
append('\n');
break;
case
TIMED_WAITING:
sb.
append("\t- waiting on " +
getLockInfo());
sb.
append('\n');
break;
default:
}
}
for (
MonitorInfo mi :
lockedMonitors) {
if (
mi.
getLockedStackDepth() ==
i) {
sb.
append("\t- locked " +
mi);
sb.
append('\n');
}
}
}
if (
i <
stackTrace.length) {
sb.
append("\t...");
sb.
append('\n');
}
LockInfo[]
locks =
getLockedSynchronizers();
if (
locks.length > 0) {
sb.
append("\n\tNumber of locked synchronizers = " +
locks.length);
sb.
append('\n');
for (
LockInfo li :
locks) {
sb.
append("\t- " +
li);
sb.
append('\n');
}
}
sb.
append('\n');
return
sb.
toString();
}
private static final int
MAX_FRAMES = 8;
/**
* Returns a <tt>ThreadInfo</tt> object represented by the
* given <tt>CompositeData</tt>.
* The given <tt>CompositeData</tt> must contain the following attributes
* unless otherwise specified below:
* <blockquote>
* <table border summary="The attributes and their types the given CompositeData contains">
* <tr>
* <th align=left>Attribute Name</th>
* <th align=left>Type</th>
* </tr>
* <tr>
* <td>threadId</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>threadName</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>threadState</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>suspended</td>
* <td><tt>java.lang.Boolean</tt></td>
* </tr>
* <tr>
* <td>inNative</td>
* <td><tt>java.lang.Boolean</tt></td>
* </tr>
* <tr>
* <td>blockedCount</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>blockedTime</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>waitedCount</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>waitedTime</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>lockInfo</td>
* <td><tt>javax.management.openmbean.CompositeData</tt>
* - the mapped type for {@link LockInfo} as specified in the
* {@link LockInfo#from} method.
* <p>
* If <tt>cd</tt> does not contain this attribute,
* the <tt>LockInfo</tt> object will be constructed from
* the value of the <tt>lockName</tt> attribute. </td>
* </tr>
* <tr>
* <td>lockName</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>lockOwnerId</td>
* <td><tt>java.lang.Long</tt></td>
* </tr>
* <tr>
* <td>lockOwnerName</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td><a name="StackTrace">stackTrace</a></td>
* <td><tt>javax.management.openmbean.CompositeData[]</tt>
* <p>
* Each element is a <tt>CompositeData</tt> representing
* StackTraceElement containing the following attributes:
* <blockquote>
* <table cellspacing=1 cellpadding=0 summary="The attributes and their types the given CompositeData contains">
* <tr>
* <th align=left>Attribute Name</th>
* <th align=left>Type</th>
* </tr>
* <tr>
* <td>className</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>methodName</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>fileName</td>
* <td><tt>java.lang.String</tt></td>
* </tr>
* <tr>
* <td>lineNumber</td>
* <td><tt>java.lang.Integer</tt></td>
* </tr>
* <tr>
* <td>nativeMethod</td>
* <td><tt>java.lang.Boolean</tt></td>
* </tr>
* </table>
* </blockquote>
* </td>
* </tr>
* <tr>
* <td>lockedMonitors</td>
* <td><tt>javax.management.openmbean.CompositeData[]</tt>
* whose element type is the mapped type for
* {@link MonitorInfo} as specified in the
* {@link MonitorInfo#from Monitor.from} method.
* <p>
* If <tt>cd</tt> does not contain this attribute,
* this attribute will be set to an empty array. </td>
* </tr>
* <tr>
* <td>lockedSynchronizers</td>
* <td><tt>javax.management.openmbean.CompositeData[]</tt>
* whose element type is the mapped type for
* {@link LockInfo} as specified in the {@link LockInfo#from} method.
* <p>
* If <tt>cd</tt> does not contain this attribute,
* this attribute will be set to an empty array. </td>
* </tr>
* </table>
* </blockquote>
*
* @param cd <tt>CompositeData</tt> representing a <tt>ThreadInfo</tt>
*
* @throws IllegalArgumentException if <tt>cd</tt> does not
* represent a <tt>ThreadInfo</tt> with the attributes described
* above.
*
* @return a <tt>ThreadInfo</tt> object represented
* by <tt>cd</tt> if <tt>cd</tt> is not <tt>null</tt>;
* <tt>null</tt> otherwise.
*/
public static
ThreadInfo from(
CompositeData cd) {
if (
cd == null) {
return null;
}
if (
cd instanceof
ThreadInfoCompositeData) {
return ((
ThreadInfoCompositeData)
cd).
getThreadInfo();
} else {
return new
ThreadInfo(
cd);
}
}
/**
* Returns an array of {@link MonitorInfo} objects, each of which
* represents an object monitor currently locked by the thread
* associated with this <tt>ThreadInfo</tt>.
* If no locked monitor was requested for this thread info or
* no monitor is locked by the thread, this method
* will return a zero-length array.
*
* @return an array of <tt>MonitorInfo</tt> objects representing
* the object monitors locked by the thread.
*
* @since 1.6
*/
public
MonitorInfo[]
getLockedMonitors() {
return
lockedMonitors;
}
/**
* Returns an array of {@link LockInfo} objects, each of which
* represents an <a href="LockInfo.html#OwnableSynchronizer">ownable
* synchronizer</a> currently locked by the thread associated with
* this <tt>ThreadInfo</tt>. If no locked synchronizer was
* requested for this thread info or no synchronizer is locked by
* the thread, this method will return a zero-length array.
*
* @return an array of <tt>LockInfo</tt> objects representing
* the ownable synchronizers locked by the thread.
*
* @since 1.6
*/
public
LockInfo[]
getLockedSynchronizers() {
return
lockedSynchronizers;
}
private static final
StackTraceElement[]
NO_STACK_TRACE =
new
StackTraceElement[0];
}