Path: blob/master/src/java.management/share/classes/java/lang/management/ThreadInfo.java
41159 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.lang.management;2627import javax.management.openmbean.ArrayType;28import javax.management.openmbean.CompositeData;29import sun.management.ManagementFactoryHelper;30import sun.management.ThreadInfoCompositeData;31import static java.lang.Thread.State.*;3233/**34* Thread information. {@code ThreadInfo} contains the information35* about a thread including:36* <h2>General thread information</h2>37* <ul>38* <li>Thread ID.</li>39* <li>Name of the thread.</li>40* <li>Whether a thread is a daemon thread</li>41* </ul>42*43* <h2>Execution information</h2>44* <ul>45* <li>Thread state.</li>46* <li>The object upon which the thread is blocked due to:47* <ul>48* <li>waiting to enter a synchronization block/method, or</li>49* <li>waiting to be notified in a {@link Object#wait Object.wait} method,50* or</li>51* <li>parking due to a {@link java.util.concurrent.locks.LockSupport#park52* LockSupport.park} call.</li>53* </ul>54* </li>55* <li>The ID of the thread that owns the object56* that the thread is blocked.</li>57* <li>Stack trace of the thread.</li>58* <li>List of object monitors locked by the thread.</li>59* <li>List of <a href="LockInfo.html#OwnableSynchronizer">60* ownable synchronizers</a> locked by the thread.</li>61* <li>Thread priority</li>62* </ul>63*64* <h3><a id="SyncStats">Synchronization Statistics</a></h3>65* <ul>66* <li>The number of times that the thread has blocked for67* synchronization or waited for notification.</li>68* <li>The accumulated elapsed time that the thread has blocked69* for synchronization or waited for notification70* since {@link ThreadMXBean#setThreadContentionMonitoringEnabled71* thread contention monitoring}72* was enabled. Some Java virtual machine implementation73* may not support this. The74* {@link ThreadMXBean#isThreadContentionMonitoringSupported()}75* method can be used to determine if a Java virtual machine76* supports this.</li>77* </ul>78*79* <p>This thread information class is designed for use in monitoring of80* the system, not for synchronization control.81*82* <h3>MXBean Mapping</h3>83* {@code ThreadInfo} is mapped to a {@link CompositeData CompositeData}84* with attributes as specified in85* the {@link #from from} method.86*87* @see ThreadMXBean#getThreadInfo88* @see ThreadMXBean#dumpAllThreads89*90* @author Mandy Chung91* @since 1.592*/9394public class ThreadInfo {95private String threadName;96private long threadId;97private long blockedTime;98private long blockedCount;99private long waitedTime;100private long waitedCount;101private LockInfo lock;102private String lockName;103private long lockOwnerId;104private String lockOwnerName;105private boolean daemon;106private boolean inNative;107private boolean suspended;108private Thread.State threadState;109private int priority;110private StackTraceElement[] stackTrace;111private MonitorInfo[] lockedMonitors;112private LockInfo[] lockedSynchronizers;113private static MonitorInfo[] EMPTY_MONITORS = new MonitorInfo[0];114private static LockInfo[] EMPTY_SYNCS = new LockInfo[0];115116/**117* Constructor of ThreadInfo created by the JVM118*119* @param t Thread120* @param state Thread state121* @param lockObj Object on which the thread is blocked122* @param lockOwner the thread holding the lock123* @param blockedCount Number of times blocked to enter a lock124* @param blockedTime Approx time blocked to enter a lock125* @param waitedCount Number of times waited on a lock126* @param waitedTime Approx time waited on a lock127* @param stackTrace Thread stack trace128*/129private ThreadInfo(Thread t, int state, Object lockObj, Thread lockOwner,130long blockedCount, long blockedTime,131long waitedCount, long waitedTime,132StackTraceElement[] stackTrace) {133initialize(t, state, lockObj, lockOwner,134blockedCount, blockedTime,135waitedCount, waitedTime, stackTrace,136EMPTY_MONITORS, EMPTY_SYNCS);137}138139/**140* Constructor of ThreadInfo created by the JVM141* for {@link ThreadMXBean#getThreadInfo(long[],boolean,boolean)}142* and {@link ThreadMXBean#dumpAllThreads}143*144* @param t Thread145* @param state Thread state146* @param lockObj Object on which the thread is blocked147* @param lockOwner the thread holding the lock148* @param blockedCount Number of times blocked to enter a lock149* @param blockedTime Approx time blocked to enter a lock150* @param waitedCount Number of times waited on a lock151* @param waitedTime Approx time waited on a lock152* @param stackTrace Thread stack trace153* @param monitors List of locked monitors154* @param stackDepths List of stack depths155* @param synchronizers List of locked synchronizers156*/157private ThreadInfo(Thread t, int state, Object lockObj, Thread lockOwner,158long blockedCount, long blockedTime,159long waitedCount, long waitedTime,160StackTraceElement[] stackTrace,161Object[] monitors,162int[] stackDepths,163Object[] synchronizers) {164int numMonitors = (monitors == null ? 0 : monitors.length);165MonitorInfo[] lockedMonitors;166if (numMonitors == 0) {167lockedMonitors = EMPTY_MONITORS;168} else {169lockedMonitors = new MonitorInfo[numMonitors];170for (int i = 0; i < numMonitors; i++) {171Object lock = monitors[i];172String className = lock.getClass().getName();173int identityHashCode = System.identityHashCode(lock);174int depth = stackDepths[i];175StackTraceElement ste = (depth >= 0 ? stackTrace[depth]176: null);177lockedMonitors[i] = new MonitorInfo(className,178identityHashCode,179depth,180ste);181}182}183184int numSyncs = (synchronizers == null ? 0 : synchronizers.length);185LockInfo[] lockedSynchronizers;186if (numSyncs == 0) {187lockedSynchronizers = EMPTY_SYNCS;188} else {189lockedSynchronizers = new LockInfo[numSyncs];190for (int i = 0; i < numSyncs; i++) {191Object lock = synchronizers[i];192String className = lock.getClass().getName();193int identityHashCode = System.identityHashCode(lock);194lockedSynchronizers[i] = new LockInfo(className,195identityHashCode);196}197}198199initialize(t, state, lockObj, lockOwner,200blockedCount, blockedTime,201waitedCount, waitedTime, stackTrace,202lockedMonitors, lockedSynchronizers);203}204205/**206* Initialize ThreadInfo object207*208* @param t Thread209* @param state Thread state210* @param lockObj Object on which the thread is blocked211* @param lockOwner the thread holding the lock212* @param blockedCount Number of times blocked to enter a lock213* @param blockedTime Approx time blocked to enter a lock214* @param waitedCount Number of times waited on a lock215* @param waitedTime Approx time waited on a lock216* @param stackTrace Thread stack trace217* @param lockedMonitors List of locked monitors218* @param lockedSynchronizers List of locked synchronizers219*/220private void initialize(Thread t, int state, Object lockObj, Thread lockOwner,221long blockedCount, long blockedTime,222long waitedCount, long waitedTime,223StackTraceElement[] stackTrace,224MonitorInfo[] lockedMonitors,225LockInfo[] lockedSynchronizers) {226this.threadId = t.getId();227this.threadName = t.getName();228this.threadState = ManagementFactoryHelper.toThreadState(state);229this.suspended = ManagementFactoryHelper.isThreadSuspended(state);230this.inNative = ManagementFactoryHelper.isThreadRunningNative(state);231this.blockedCount = blockedCount;232this.blockedTime = blockedTime;233this.waitedCount = waitedCount;234this.waitedTime = waitedTime;235this.daemon = t.isDaemon();236this.priority = t.getPriority();237238if (lockObj == null) {239this.lock = null;240this.lockName = null;241} else {242this.lock = new LockInfo(lockObj);243this.lockName =244lock.getClassName() + '@' +245Integer.toHexString(lock.getIdentityHashCode());246}247if (lockOwner == null) {248this.lockOwnerId = -1;249this.lockOwnerName = null;250} else {251this.lockOwnerId = lockOwner.getId();252this.lockOwnerName = lockOwner.getName();253}254if (stackTrace == null) {255this.stackTrace = NO_STACK_TRACE;256} else {257this.stackTrace = stackTrace;258}259this.lockedMonitors = lockedMonitors;260this.lockedSynchronizers = lockedSynchronizers;261}262263/*264* Constructs a {@code ThreadInfo} object from a265* {@link CompositeData CompositeData}.266*267* @throws IllegalArgumentException if the given CompositeData does not268* contain all of the attributes defined for ThreadInfo of version <= N.269*270* @see ThreadInfo#from271*/272private ThreadInfo(CompositeData cd) {273ThreadInfoCompositeData ticd = ThreadInfoCompositeData.getInstance(cd);274275threadId = ticd.threadId();276threadName = ticd.threadName();277blockedTime = ticd.blockedTime();278blockedCount = ticd.blockedCount();279waitedTime = ticd.waitedTime();280waitedCount = ticd.waitedCount();281lockName = ticd.lockName();282lockOwnerId = ticd.lockOwnerId();283lockOwnerName = ticd.lockOwnerName();284threadState = ticd.threadState();285suspended = ticd.suspended();286inNative = ticd.inNative();287stackTrace = ticd.stackTrace();288lock = ticd.lockInfo();289lockedMonitors = ticd.lockedMonitors();290lockedSynchronizers = ticd.lockedSynchronizers();291daemon = ticd.isDaemon();292priority = ticd.getPriority();293}294295/**296* Returns the ID of the thread associated with this {@code ThreadInfo}.297*298* @return the ID of the associated thread.299*/300public long getThreadId() {301return threadId;302}303304/**305* Returns the name of the thread associated with this {@code ThreadInfo}.306*307* @return the name of the associated thread.308*/309public String getThreadName() {310return threadName;311}312313/**314* Returns the state of the thread associated with this {@code ThreadInfo}.315*316* @return {@code Thread.State} of the associated thread.317*/318public Thread.State getThreadState() {319return threadState;320}321322/**323* Returns the approximate accumulated elapsed time (in milliseconds)324* that the thread associated with this {@code ThreadInfo}325* has blocked to enter or reenter a monitor326* since thread contention monitoring is enabled.327* I.e. the total accumulated time the thread has been in the328* {@link java.lang.Thread.State#BLOCKED BLOCKED} state since thread329* contention monitoring was last enabled.330* This method returns {@code -1} if thread contention monitoring331* is disabled.332*333* <p>The Java virtual machine may measure the time with a high334* resolution timer. This statistic is reset when335* the thread contention monitoring is reenabled.336*337* @return the approximate accumulated elapsed time in milliseconds338* that a thread entered the {@code BLOCKED} state;339* {@code -1} if thread contention monitoring is disabled.340*341* @throws java.lang.UnsupportedOperationException if the Java342* virtual machine does not support this operation.343*344* @see ThreadMXBean#isThreadContentionMonitoringSupported345* @see ThreadMXBean#setThreadContentionMonitoringEnabled346*/347public long getBlockedTime() {348return blockedTime;349}350351/**352* Returns the total number of times that353* the thread associated with this {@code ThreadInfo}354* blocked to enter or reenter a monitor.355* I.e. the number of times a thread has been in the356* {@link java.lang.Thread.State#BLOCKED BLOCKED} state.357*358* @return the total number of times that the thread359* entered the {@code BLOCKED} state.360*/361public long getBlockedCount() {362return blockedCount;363}364365/**366* Returns the approximate accumulated elapsed time (in milliseconds)367* that the thread associated with this {@code ThreadInfo}368* has waited for notification369* since thread contention monitoring is enabled.370* I.e. the total accumulated time the thread has been in the371* {@link java.lang.Thread.State#WAITING WAITING}372* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state373* since thread contention monitoring is enabled.374* This method returns {@code -1} if thread contention monitoring375* is disabled.376*377* <p>The Java virtual machine may measure the time with a high378* resolution timer. This statistic is reset when379* the thread contention monitoring is reenabled.380*381* @return the approximate accumulated elapsed time in milliseconds382* that a thread has been in the {@code WAITING} or383* {@code TIMED_WAITING} state;384* {@code -1} if thread contention monitoring is disabled.385*386* @throws java.lang.UnsupportedOperationException if the Java387* virtual machine does not support this operation.388*389* @see ThreadMXBean#isThreadContentionMonitoringSupported390* @see ThreadMXBean#setThreadContentionMonitoringEnabled391*/392public long getWaitedTime() {393return waitedTime;394}395396/**397* Returns the total number of times that398* the thread associated with this {@code ThreadInfo}399* waited for notification.400* I.e. the number of times that a thread has been401* in the {@link java.lang.Thread.State#WAITING WAITING}402* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state.403*404* @return the total number of times that the thread405* was in the {@code WAITING} or {@code TIMED_WAITING} state.406*/407public long getWaitedCount() {408return waitedCount;409}410411/**412* Returns the {@code LockInfo} of an object for which413* the thread associated with this {@code ThreadInfo}414* is blocked waiting.415* A thread can be blocked waiting for one of the following:416* <ul>417* <li>an object monitor to be acquired for entering or reentering418* a synchronization block/method.419* <br>The thread is in the {@link java.lang.Thread.State#BLOCKED BLOCKED}420* state waiting to enter the {@code synchronized} statement421* or method.422* </li>423* <li>an object monitor to be notified by another thread.424* <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING}425* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state426* due to a call to the {@link Object#wait Object.wait} method.427* </li>428* <li>a synchronization object responsible for the thread parking.429* <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING}430* or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state431* due to a call to the432* {@link java.util.concurrent.locks.LockSupport#park(Object)433* LockSupport.park} method. The synchronization object434* is the object returned from435* {@link java.util.concurrent.locks.LockSupport#getBlocker436* LockSupport.getBlocker} method. Typically it is an437* <a href="LockInfo.html#OwnableSynchronizer"> ownable synchronizer</a>438* or a {@link java.util.concurrent.locks.Condition Condition}.</li>439* </ul>440*441* <p>This method returns {@code null} if the thread is not in any of442* the above conditions.443*444* @return {@code LockInfo} of an object for which the thread445* is blocked waiting if any; {@code null} otherwise.446* @since 1.6447*/448public LockInfo getLockInfo() {449return lock;450}451452/**453* Returns the {@link LockInfo#toString string representation}454* of an object for which the thread associated with this455* {@code ThreadInfo} is blocked waiting.456* This method is equivalent to calling:457* <blockquote>458* <pre>459* getLockInfo().toString()460* </pre></blockquote>461*462* <p>This method will return {@code null} if this thread is not blocked463* waiting for any object or if the object is not owned by any thread.464*465* @return the string representation of the object on which466* the thread is blocked if any;467* {@code null} otherwise.468*469* @see #getLockInfo470*/471public String getLockName() {472return lockName;473}474475/**476* Returns the ID of the thread which owns the object477* for which the thread associated with this {@code ThreadInfo}478* is blocked waiting.479* This method will return {@code -1} if this thread is not blocked480* waiting for any object or if the object is not owned by any thread.481*482* @return the thread ID of the owner thread of the object483* this thread is blocked on;484* {@code -1} if this thread is not blocked485* or if the object is not owned by any thread.486*487* @see #getLockInfo488*/489public long getLockOwnerId() {490return lockOwnerId;491}492493/**494* Returns the name of the thread which owns the object495* for which the thread associated with this {@code ThreadInfo}496* is blocked waiting.497* This method will return {@code null} if this thread is not blocked498* waiting for any object or if the object is not owned by any thread.499*500* @return the name of the thread that owns the object501* this thread is blocked on;502* {@code null} if this thread is not blocked503* or if the object is not owned by any thread.504*505* @see #getLockInfo506*/507public String getLockOwnerName() {508return lockOwnerName;509}510511/**512* Returns the stack trace of the thread513* associated with this {@code ThreadInfo}.514* If no stack trace was requested for this thread info, this method515* will return a zero-length array.516* If the returned array is of non-zero length then the first element of517* the array represents the top of the stack, which is the most recent518* method invocation in the sequence. The last element of the array519* represents the bottom of the stack, which is the least recent method520* invocation in the sequence.521*522* <p>Some Java virtual machines may, under some circumstances, omit one523* or more stack frames from the stack trace. In the extreme case,524* a virtual machine that has no stack trace information concerning525* the thread associated with this {@code ThreadInfo}526* is permitted to return a zero-length array from this method.527*528* @return an array of {@code StackTraceElement} objects of the thread.529*/530public StackTraceElement[] getStackTrace() {531return stackTrace.clone();532}533534/**535* Tests if the thread associated with this {@code ThreadInfo}536* is suspended. This method returns {@code true} if537* {@link Thread#suspend} has been called.538*539* @return {@code true} if the thread is suspended;540* {@code false} otherwise.541*/542public boolean isSuspended() {543return suspended;544}545546/**547* Tests if the thread associated with this {@code ThreadInfo}548* is executing native code via the Java Native Interface (JNI).549* The JNI native code does not include550* the virtual machine support code or the compiled native551* code generated by the virtual machine.552*553* @return {@code true} if the thread is executing native code;554* {@code false} otherwise.555*/556public boolean isInNative() {557return inNative;558}559560/**561* Tests if the thread associated with this {@code ThreadInfo} is562* a {@linkplain Thread#isDaemon daemon thread}.563*564* @return {@code true} if the thread is a daemon thread,565* {@code false} otherwise.566* @see Thread#isDaemon567* @since 9568*/569public boolean isDaemon() {570return daemon;571}572573/**574* Returns the {@linkplain Thread#getPriority() thread priority} of the575* thread associated with this {@code ThreadInfo}.576*577* @return The priority of the thread associated with this578* {@code ThreadInfo}.579* @since 9580*/581public int getPriority() {582return priority;583}584585/**586* Returns a string representation of this thread info.587* The format of this string depends on the implementation.588* The returned string will typically include589* the {@linkplain #getThreadName thread name},590* the {@linkplain #getThreadId thread ID},591* its {@linkplain #getThreadState state},592* and a {@linkplain #getStackTrace stack trace} if any.593*594* @return a string representation of this thread info.595*/596public String toString() {597StringBuilder sb = new StringBuilder("\"" + getThreadName() + "\"" +598(daemon ? " daemon" : "") +599" prio=" + priority +600" Id=" + getThreadId() + " " +601getThreadState());602if (getLockName() != null) {603sb.append(" on " + getLockName());604}605if (getLockOwnerName() != null) {606sb.append(" owned by \"" + getLockOwnerName() +607"\" Id=" + getLockOwnerId());608}609if (isSuspended()) {610sb.append(" (suspended)");611}612if (isInNative()) {613sb.append(" (in native)");614}615sb.append('\n');616int i = 0;617for (; i < stackTrace.length && i < MAX_FRAMES; i++) {618StackTraceElement ste = stackTrace[i];619sb.append("\tat " + ste.toString());620sb.append('\n');621if (i == 0 && getLockInfo() != null) {622Thread.State ts = getThreadState();623switch (ts) {624case BLOCKED:625sb.append("\t- blocked on " + getLockInfo());626sb.append('\n');627break;628case WAITING:629sb.append("\t- waiting on " + getLockInfo());630sb.append('\n');631break;632case TIMED_WAITING:633sb.append("\t- waiting on " + getLockInfo());634sb.append('\n');635break;636default:637}638}639640for (MonitorInfo mi : lockedMonitors) {641if (mi.getLockedStackDepth() == i) {642sb.append("\t- locked " + mi);643sb.append('\n');644}645}646}647if (i < stackTrace.length) {648sb.append("\t...");649sb.append('\n');650}651652LockInfo[] locks = getLockedSynchronizers();653if (locks.length > 0) {654sb.append("\n\tNumber of locked synchronizers = " + locks.length);655sb.append('\n');656for (LockInfo li : locks) {657sb.append("\t- " + li);658sb.append('\n');659}660}661sb.append('\n');662return sb.toString();663}664private static final int MAX_FRAMES = 8;665666/**667* Returns a {@code ThreadInfo} object represented by the668* given {@code CompositeData}.669*670* <a id="attributes"></a>671* A {@code CompositeData} representing a {@code ThreadInfo} of672* version <em>N</em> must contain all of the attributes defined673* in version ≤ <em>N</em> unless specified otherwise.674* The same rule applies the composite type of the given675* {@code CompositeData} and transitively to attributes whose676* {@linkplain CompositeData#getCompositeType() type} or677* {@linkplain ArrayType#getElementOpenType() component type} is678* {@code CompositeType}.679* <p>680* A {@code CompositeData} representing {@code ThreadInfo} of681* version <em>N</em> contains {@code "stackTrace"} attribute and682* {@code "lockedMonitors"} attribute representing683* an array of {@code StackTraceElement} and684* an array of {@link MonitorInfo} respectively685* and their types are of version <em>N</em>.686* The {@code "lockedStackFrame"} attribute in687* {@link MonitorInfo#from(CompositeData) MonitorInfo}'s composite type688* must represent {@code StackTraceElement} of the same version <em>N</em>.689* Otherwise, this method will throw {@code IllegalArgumentException}.690*691* <table class="striped" style="margin-left:2em">692* <caption style="display:none">The attributes and their types for ThreadInfo's composite data</caption>693* <thead>694* <tr>695* <th scope="col">Attribute Name</th>696* <th scope="col">Type</th>697* <th scope="col">Since</th>698* </tr>699* </thead>700* <tbody style="text-align:left">701* <tr>702* <th scope="row">threadId</th>703* <td>{@code java.lang.Long}</td>704* <td>5</td>705* </tr>706* <tr>707* <th scope="row">threadName</th>708* <td>{@code java.lang.String}</td>709* <td>5</td>710* </tr>711* <tr>712* <th scope="row">threadState</th>713* <td>{@code java.lang.String}</td>714* <td>5</td>715* </tr>716* <tr>717* <th scope="row">suspended</th>718* <td>{@code java.lang.Boolean}</td>719* <td>5</td>720* </tr>721* <tr>722* <th scope="row">inNative</th>723* <td>{@code java.lang.Boolean}</td>724* <td>5</td>725* </tr>726* <tr>727* <th scope="row">blockedCount</th>728* <td>{@code java.lang.Long}</td>729* <td>5</td>730* </tr>731* <tr>732* <th scope="row">blockedTime</th>733* <td>{@code java.lang.Long}</td>734* <td>5</td>735* </tr>736* <tr>737* <th scope="row">waitedCount</th>738* <td>{@code java.lang.Long}</td>739* <td>5</td>740* </tr>741* <tr>742* <th scope="row">waitedTime</th>743* <td>{@code java.lang.Long}</td>744* <td>5</td>745* </tr>746* <tr>747* <th scope="row">lockName</th>748* <td>{@code java.lang.String}</td>749* <td>5</td>750* </tr>751* <tr>752* <th scope="row">lockOwnerId</th>753* <td>{@code java.lang.Long}</td>754* <td>5</td>755* </tr>756* <tr>757* <th scope="row">lockOwnerName</th>758* <td>{@code java.lang.String}</td>759* <td>5</td>760* </tr>761* <tr>762* <th scope="row"><a id="StackTrace">stackTrace</a></th>763* <td>{@code javax.management.openmbean.CompositeData[]}, each element764* is a {@code CompositeData} representing {@code StackTraceElement}765* as specified <a href="#stackTraceElement">below</a>.766* </td>767* <td>5</td>768* </tr>769* <tr>770* <th scope="row">lockInfo</th>771* <td>{@code javax.management.openmbean.CompositeData}772* - the mapped type for {@link LockInfo} as specified in the773* {@link LockInfo#from} method.774* <p>775* If the given {@code CompositeData} does not contain this attribute,776* the {@code LockInfo} object will be constructed from777* the value of the {@code lockName} attribute.</td>778* <td>6</td>779* </tr>780* <tr>781* <th scope="row">lockedMonitors</th>782* <td>{@code javax.management.openmbean.CompositeData[]}783* whose element type is the mapped type for784* {@link MonitorInfo} as specified in the785* {@link MonitorInfo#from MonitorInfo.from} method.786* <p>787* If the given {@code CompositeData} does not contain this attribute,788* this attribute will be set to an empty array.</td>789* <td>6</td>790* </tr>791* <tr>792* <th scope="row">lockedSynchronizers</th>793* <td>{@code javax.management.openmbean.CompositeData[]}794* whose element type is the mapped type for795* {@link LockInfo} as specified in the {@link LockInfo#from} method.796* <p>797* If the given {@code CompositeData} does not contain this attribute,798* this attribute will be set to an empty array.</td>799* <td>6</td>800* </tr>801* <tr>802* <th scope="row">daemon</th>803* <td>{@code java.lang.Boolean}804* <p>805* If the given {@code CompositeData} does not contain this attribute,806* this attribute will be set to {@code false}.</td>807* <td>9</td>808* </tr>809* <tr>810* <th scope="row">priority</th>811* <td>{@code java.lang.Integer}812* <p>813* If the given {@code CompositeData} does not contain this attribute,814* This attribute will be set to {@link Thread#NORM_PRIORITY}.</td>815* <td>9</td>816* </tr>817* </tbody>818* </table>819*820* <a id="stackTraceElement">A {@code CompositeData} representing821* {@code StackTraceElement}</a> of version <em>N</em> must contain822* all of the attributes defined in version ≤ <em>N</em>823* unless specified otherwise.824*825* <table class="striped" style="margin-left:2em">826* <caption style="display:none">The attributes and their types for StackTraceElement's composite data</caption>827* <thead style="text-align:center">828* <tr>829* <th scope="col">Attribute Name</th>830* <th scope="col">Type</th>831* <th scope="col">Since</th>832* </tr>833* </thead>834* <tbody style="text-align:left">835* <tr>836* <th scope="row">classLoaderName</th>837* <td>{@code java.lang.String}</td>838* <td>9</td>839* </tr>840* <tr>841* <th scope="row">moduleName</th>842* <td>{@code java.lang.String}</td>843* <td>9</td>844* </tr>845* <tr>846* <th scope="row">moduleVersion</th>847* <td>{@code java.lang.String}</td>848* <td>9</td>849* </tr>850* <tr>851* <th scope="row">className</th>852* <td>{@code java.lang.String}</td>853* <td>5</td>854* </tr>855* <tr>856* <th scope="row">methodName</th>857* <td>{@code java.lang.String}</td>858* <td>5</td>859* </tr>860* <tr>861* <th scope="row">fileName</th>862* <td>{@code java.lang.String}</td>863* <td>5</td>864* </tr>865* <tr>866* <th scope="row">lineNumber</th>867* <td>{@code java.lang.Integer}</td>868* <td>5</td>869* </tr>870* <tr>871* <th scope="row">nativeMethod</th>872* <td>{@code java.lang.Boolean}</td>873* <td>5</td>874* </tr>875* </tbody>876* </table>877*878* @param cd {@code CompositeData} representing a {@code ThreadInfo}879*880* @throws IllegalArgumentException if the given {@code cd} and881* its composite type does not contain all of882* <a href="#attributes">the attributes</a> defined for a883* {@code ThreadInfo} of a specific runtime version.884*885* @return a {@code ThreadInfo} object represented886* by {@code cd} if {@code cd} is not {@code null};887* {@code null} otherwise.888*889* @revised 9890*/891public static ThreadInfo from(CompositeData cd) {892if (cd == null) {893return null;894}895896if (cd instanceof ThreadInfoCompositeData) {897return ((ThreadInfoCompositeData) cd).getThreadInfo();898} else {899return new ThreadInfo(cd);900}901}902903/**904* Returns an array of {@link MonitorInfo} objects, each of which905* represents an object monitor currently locked by the thread906* associated with this {@code ThreadInfo}.907* If no locked monitor was requested for this thread info or908* no monitor is locked by the thread, this method909* will return a zero-length array.910*911* @return an array of {@code MonitorInfo} objects representing912* the object monitors locked by the thread.913*914* @since 1.6915*/916public MonitorInfo[] getLockedMonitors() {917return lockedMonitors.clone();918}919920/**921* Returns an array of {@link LockInfo} objects, each of which922* represents an <a href="LockInfo.html#OwnableSynchronizer">ownable923* synchronizer</a> currently locked by the thread associated with924* this {@code ThreadInfo}. If no locked synchronizer was925* requested for this thread info or no synchronizer is locked by926* the thread, this method will return a zero-length array.927*928* @return an array of {@code LockInfo} objects representing929* the ownable synchronizers locked by the thread.930*931* @since 1.6932*/933public LockInfo[] getLockedSynchronizers() {934return lockedSynchronizers.clone();935}936937private static final StackTraceElement[] NO_STACK_TRACE =938new StackTraceElement[0];939}940941942