1 /* 2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.management; 27 28 import javax.management.openmbean.CompositeData; 29 import sun.management.ManagementFactoryHelper; 30 import sun.management.ThreadInfoCompositeData; 31 import static java.lang.Thread.State.*; 32 33 /** 34 * Thread information. <tt>ThreadInfo</tt> contains the information 35 * about a thread including: 36 * <h3>General thread information</h3> 37 * <ul> 38 * <li>Thread ID.</li> 39 * <li>Name of the thread.</li> 40 * </ul> 41 * 42 * <h3>Execution information</h3> 43 * <ul> 44 * <li>Thread state.</li> 45 * <li>The object upon which the thread is blocked due to: 46 * <ul> 47 * <li>waiting to enter a synchronization block/method, or</li> 48 * <li>waiting to be notified in a {@link Object#wait Object.wait} method, 49 * or</li> 50 * <li>parking due to a {@link java.util.concurrent.locks.LockSupport#park 51 * LockSupport.park} call.</li> 52 * </ul> 53 * </li> 54 * <li>The ID of the thread that owns the object 55 * that the thread is blocked.</li> 56 * <li>Stack trace of the thread.</li> 57 * <li>List of object monitors locked by the thread.</li> 58 * <li>List of <a href="LockInfo.html#OwnableSynchronizer"> 59 * ownable synchronizers</a> locked by the thread.</li> 60 * </ul> 61 * 62 * <h4><a name="SyncStats">Synchronization Statistics</a></h4> 63 * <ul> 64 * <li>The number of times that the thread has blocked for 65 * synchronization or waited for notification.</li> 66 * <li>The accumulated elapsed time that the thread has blocked 67 * for synchronization or waited for notification 68 * since {@link ThreadMXBean#setThreadContentionMonitoringEnabled 69 * thread contention monitoring} 70 * was enabled. Some Java virtual machine implementation 71 * may not support this. The 72 * {@link ThreadMXBean#isThreadContentionMonitoringSupported()} 73 * method can be used to determine if a Java virtual machine 74 * supports this.</li> 75 * </ul> 76 * 77 * <p>This thread information class is designed for use in monitoring of 78 * the system, not for synchronization control. 79 * 80 * <h4>MXBean Mapping</h4> 81 * <tt>ThreadInfo</tt> is mapped to a {@link CompositeData CompositeData} 82 * with attributes as specified in 83 * the {@link #from from} method. 84 * 85 * @see ThreadMXBean#getThreadInfo 86 * @see ThreadMXBean#dumpAllThreads 87 * 88 * @author Mandy Chung 89 * @since 1.5 90 */ 91 92 public class ThreadInfo { 93 private String threadName; 94 private long threadId; 95 private long blockedTime; 96 private long blockedCount; 97 private long waitedTime; 98 private long waitedCount; 99 private LockInfo lock; 100 private String lockName; 101 private long lockOwnerId; 102 private String lockOwnerName; 103 private boolean inNative; 104 private boolean suspended; 105 private Thread.State threadState; 106 private StackTraceElement[] stackTrace; 107 private MonitorInfo[] lockedMonitors; 108 private LockInfo[] lockedSynchronizers; 109 110 private static MonitorInfo[] EMPTY_MONITORS = new MonitorInfo[0]; 111 private static LockInfo[] EMPTY_SYNCS = new LockInfo[0]; 112 113 /** 114 * Constructor of ThreadInfo created by the JVM 115 * 116 * @param t Thread 117 * @param state Thread state 118 * @param lockObj Object on which the thread is blocked 119 * @param lockOwner the thread holding the lock 120 * @param blockedCount Number of times blocked to enter a lock 121 * @param blockedTime Approx time blocked to enter a lock 122 * @param waitedCount Number of times waited on a lock 123 * @param waitedTime Approx time waited on a lock 124 * @param stackTrace Thread stack trace 125 */ 126 private ThreadInfo(Thread t, int state, Object lockObj, Thread lockOwner, 127 long blockedCount, long blockedTime, 128 long waitedCount, long waitedTime, 129 StackTraceElement[] stackTrace) { 130 initialize(t, state, lockObj, lockOwner, 131 blockedCount, blockedTime, 132 waitedCount, waitedTime, stackTrace, 133 EMPTY_MONITORS, EMPTY_SYNCS); 134 } 135 136 /** 137 * Constructor of ThreadInfo created by the JVM 138 * for {@link ThreadMXBean#getThreadInfo(long[],boolean,boolean)} 139 * and {@link ThreadMXBean#dumpAllThreads} 140 * 141 * @param t Thread 142 * @param state Thread state 143 * @param lockObj Object on which the thread is blocked 144 * @param lockOwner the thread holding the lock 145 * @param blockedCount Number of times blocked to enter a lock 146 * @param blockedTime Approx time blocked to enter a lock 147 * @param waitedCount Number of times waited on a lock 148 * @param waitedTime Approx time waited on a lock 149 * @param stackTrace Thread stack trace 150 * @param monitors List of locked monitors 151 * @param stackDepths List of stack depths 152 * @param synchronizers List of locked synchronizers 153 */ 154 private ThreadInfo(Thread t, int state, Object lockObj, Thread lockOwner, 155 long blockedCount, long blockedTime, 156 long waitedCount, long waitedTime, 157 StackTraceElement[] stackTrace, 158 Object[] monitors, 159 int[] stackDepths, 160 Object[] synchronizers) { 161 int numMonitors = (monitors == null ? 0 : monitors.length); 162 MonitorInfo[] lockedMonitors; 163 if (numMonitors == 0) { 164 lockedMonitors = EMPTY_MONITORS; 165 } else { 166 lockedMonitors = new MonitorInfo[numMonitors]; 167 for (int i = 0; i < numMonitors; i++) { 168 Object lock = monitors[i]; 169 String className = lock.getClass().getName(); 170 int identityHashCode = System.identityHashCode(lock); 171 int depth = stackDepths[i]; 172 StackTraceElement ste = (depth >= 0 ? stackTrace[depth] 173 : null); 174 lockedMonitors[i] = new MonitorInfo(className, 175 identityHashCode, 176 depth, 177 ste); 178 } 179 } 180 181 int numSyncs = (synchronizers == null ? 0 : synchronizers.length); 182 LockInfo[] lockedSynchronizers; 183 if (numSyncs == 0) { 184 lockedSynchronizers = EMPTY_SYNCS; 185 } else { 186 lockedSynchronizers = new LockInfo[numSyncs]; 187 for (int i = 0; i < numSyncs; i++) { 188 Object lock = synchronizers[i]; 189 String className = lock.getClass().getName(); 190 int identityHashCode = System.identityHashCode(lock); 191 lockedSynchronizers[i] = new LockInfo(className, 192 identityHashCode); 193 } 194 } 195 196 initialize(t, state, lockObj, lockOwner, 197 blockedCount, blockedTime, 198 waitedCount, waitedTime, stackTrace, 199 lockedMonitors, lockedSynchronizers); 200 } 201 202 /** 203 * Initialize ThreadInfo object 204 * 205 * @param t Thread 206 * @param state Thread state 207 * @param lockObj Object on which the thread is blocked 208 * @param lockOwner the thread holding the lock 209 * @param blockedCount Number of times blocked to enter a lock 210 * @param blockedTime Approx time blocked to enter a lock 211 * @param waitedCount Number of times waited on a lock 212 * @param waitedTime Approx time waited on a lock 213 * @param stackTrace Thread stack trace 214 * @param lockedMonitors List of locked monitors 215 * @param lockedSynchronizers List of locked synchronizers 216 */ 217 private void initialize(Thread t, int state, Object lockObj, Thread lockOwner, 218 long blockedCount, long blockedTime, 219 long waitedCount, long waitedTime, 220 StackTraceElement[] stackTrace, 221 MonitorInfo[] lockedMonitors, 222 LockInfo[] lockedSynchronizers) { 223 this.threadId = t.getId(); 224 this.threadName = t.getName(); 225 this.threadState = ManagementFactoryHelper.toThreadState(state); 226 this.suspended = ManagementFactoryHelper.isThreadSuspended(state); 227 this.inNative = ManagementFactoryHelper.isThreadRunningNative(state); 228 this.blockedCount = blockedCount; 229 this.blockedTime = blockedTime; 230 this.waitedCount = waitedCount; 231 this.waitedTime = waitedTime; 232 233 if (lockObj == null) { 234 this.lock = null; 235 this.lockName = null; 236 } else { 237 this.lock = new LockInfo(lockObj); 238 this.lockName = 239 lock.getClassName() + '@' + 240 Integer.toHexString(lock.getIdentityHashCode()); 241 } 242 if (lockOwner == null) { 243 this.lockOwnerId = -1; 244 this.lockOwnerName = null; 245 } else { 246 this.lockOwnerId = lockOwner.getId(); 247 this.lockOwnerName = lockOwner.getName(); 248 } 249 if (stackTrace == null) { 250 this.stackTrace = NO_STACK_TRACE; 251 } else { 252 this.stackTrace = stackTrace; 253 } 254 this.lockedMonitors = lockedMonitors; 255 this.lockedSynchronizers = lockedSynchronizers; 256 } 257 258 /* 259 * Constructs a <tt>ThreadInfo</tt> object from a 260 * {@link CompositeData CompositeData}. 261 */ 262 private ThreadInfo(CompositeData cd) { 263 ThreadInfoCompositeData ticd = ThreadInfoCompositeData.getInstance(cd); 264 265 threadId = ticd.threadId(); 266 threadName = ticd.threadName(); 267 blockedTime = ticd.blockedTime(); 268 blockedCount = ticd.blockedCount(); 269 waitedTime = ticd.waitedTime(); 270 waitedCount = ticd.waitedCount(); 271 lockName = ticd.lockName(); 272 lockOwnerId = ticd.lockOwnerId(); 273 lockOwnerName = ticd.lockOwnerName(); 274 threadState = ticd.threadState(); 275 suspended = ticd.suspended(); 276 inNative = ticd.inNative(); 277 stackTrace = ticd.stackTrace(); 278 279 // 6.0 attributes 280 if (ticd.isCurrentVersion()) { 281 lock = ticd.lockInfo(); 282 lockedMonitors = ticd.lockedMonitors(); 283 lockedSynchronizers = ticd.lockedSynchronizers(); 284 } else { 285 // lockInfo is a new attribute added in 1.6 ThreadInfo 286 // If cd is a 5.0 version, construct the LockInfo object 287 // from the lockName value. 288 if (lockName != null) { 289 String result[] = lockName.split("@"); 290 if (result.length == 2) { 291 int identityHashCode = Integer.parseInt(result[1], 16); 292 lock = new LockInfo(result[0], identityHashCode); 293 } else { 294 assert result.length == 2; 295 lock = null; 296 } 297 } else { 298 lock = null; 299 } 300 lockedMonitors = EMPTY_MONITORS; 301 lockedSynchronizers = EMPTY_SYNCS; 302 } 303 } 304 305 /** 306 * Returns the ID of the thread associated with this <tt>ThreadInfo</tt>. 307 * 308 * @return the ID of the associated thread. 309 */ 310 public long getThreadId() { 311 return threadId; 312 } 313 314 /** 315 * Returns the name of the thread associated with this <tt>ThreadInfo</tt>. 316 * 317 * @return the name of the associated thread. 318 */ 319 public String getThreadName() { 320 return threadName; 321 } 322 323 /** 324 * Returns the state of the thread associated with this <tt>ThreadInfo</tt>. 325 * 326 * @return <tt>Thread.State</tt> of the associated thread. 327 */ 328 public Thread.State getThreadState() { 329 return threadState; 330 } 331 332 /** 333 * Returns the approximate accumulated elapsed time (in milliseconds) 334 * that the thread associated with this <tt>ThreadInfo</tt> 335 * has blocked to enter or reenter a monitor 336 * since thread contention monitoring is enabled. 337 * I.e. the total accumulated time the thread has been in the 338 * {@link java.lang.Thread.State#BLOCKED BLOCKED} state since thread 339 * contention monitoring was last enabled. 340 * This method returns <tt>-1</tt> if thread contention monitoring 341 * is disabled. 342 * 343 * <p>The Java virtual machine may measure the time with a high 344 * resolution timer. This statistic is reset when 345 * the thread contention monitoring is reenabled. 346 * 347 * @return the approximate accumulated elapsed time in milliseconds 348 * that a thread entered the <tt>BLOCKED</tt> state; 349 * <tt>-1</tt> if thread contention monitoring is disabled. 350 * 351 * @throws java.lang.UnsupportedOperationException if the Java 352 * virtual machine does not support this operation. 353 * 354 * @see ThreadMXBean#isThreadContentionMonitoringSupported 355 * @see ThreadMXBean#setThreadContentionMonitoringEnabled 356 */ 357 public long getBlockedTime() { 358 return blockedTime; 359 } 360 361 /** 362 * Returns the total number of times that 363 * the thread associated with this <tt>ThreadInfo</tt> 364 * blocked to enter or reenter a monitor. 365 * I.e. the number of times a thread has been in the 366 * {@link java.lang.Thread.State#BLOCKED BLOCKED} state. 367 * 368 * @return the total number of times that the thread 369 * entered the <tt>BLOCKED</tt> state. 370 */ 371 public long getBlockedCount() { 372 return blockedCount; 373 } 374 375 /** 376 * Returns the approximate accumulated elapsed time (in milliseconds) 377 * that the thread associated with this <tt>ThreadInfo</tt> 378 * has waited for notification 379 * since thread contention monitoring is enabled. 380 * I.e. the total accumulated time the thread has been in the 381 * {@link java.lang.Thread.State#WAITING WAITING} 382 * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state 383 * since thread contention monitoring is enabled. 384 * This method returns <tt>-1</tt> if thread contention monitoring 385 * is disabled. 386 * 387 * <p>The Java virtual machine may measure the time with a high 388 * resolution timer. This statistic is reset when 389 * the thread contention monitoring is reenabled. 390 * 391 * @return the approximate accumulated elapsed time in milliseconds 392 * that a thread has been in the <tt>WAITING</tt> or 393 * <tt>TIMED_WAITING</tt> state; 394 * <tt>-1</tt> if thread contention monitoring is disabled. 395 * 396 * @throws java.lang.UnsupportedOperationException if the Java 397 * virtual machine does not support this operation. 398 * 399 * @see ThreadMXBean#isThreadContentionMonitoringSupported 400 * @see ThreadMXBean#setThreadContentionMonitoringEnabled 401 */ 402 public long getWaitedTime() { 403 return waitedTime; 404 } 405 406 /** 407 * Returns the total number of times that 408 * the thread associated with this <tt>ThreadInfo</tt> 409 * waited for notification. 410 * I.e. the number of times that a thread has been 411 * in the {@link java.lang.Thread.State#WAITING WAITING} 412 * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state. 413 * 414 * @return the total number of times that the thread 415 * was in the <tt>WAITING</tt> or <tt>TIMED_WAITING</tt> state. 416 */ 417 public long getWaitedCount() { 418 return waitedCount; 419 } 420 421 /** 422 * Returns the <tt>LockInfo</tt> of an object for which 423 * the thread associated with this <tt>ThreadInfo</tt> 424 * is blocked waiting. 425 * A thread can be blocked waiting for one of the following: 426 * <ul> 427 * <li>an object monitor to be acquired for entering or reentering 428 * a synchronization block/method. 429 * <br>The thread is in the {@link java.lang.Thread.State#BLOCKED BLOCKED} 430 * state waiting to enter the <tt>synchronized</tt> statement 431 * or method. 432 * </li> 433 * <li>an object monitor to be notified by another thread. 434 * <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING} 435 * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state 436 * due to a call to the {@link Object#wait Object.wait} method. 437 * </li> 438 * <li>a synchronization object responsible for the thread parking. 439 * <br>The thread is in the {@link java.lang.Thread.State#WAITING WAITING} 440 * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state 441 * due to a call to the 442 * {@link java.util.concurrent.locks.LockSupport#park(Object) 443 * LockSupport.park} method. The synchronization object 444 * is the object returned from 445 * {@link java.util.concurrent.locks.LockSupport#getBlocker 446 * LockSupport.getBlocker} method. Typically it is an 447 * <a href="LockInfo.html#OwnableSynchronizer"> ownable synchronizer</a> 448 * or a {@link java.util.concurrent.locks.Condition Condition}.</li> 449 * </ul> 450 * 451 * <p>This method returns <tt>null</tt> if the thread is not in any of 452 * the above conditions. 453 * 454 * @return <tt>LockInfo</tt> of an object for which the thread 455 * is blocked waiting if any; <tt>null</tt> otherwise. 456 * @since 1.6 457 */ 458 public LockInfo getLockInfo() { 459 return lock; 460 } 461 462 /** 463 * Returns the {@link LockInfo#toString string representation} 464 * of an object for which the thread associated with this 465 * <tt>ThreadInfo</tt> is blocked waiting. 466 * This method is equivalent to calling: 467 * <blockquote> 468 * <pre> 469 * getLockInfo().toString() 470 * </pre></blockquote> 471 * 472 * <p>This method will return <tt>null</tt> if this thread is not blocked 473 * waiting for any object or if the object is not owned by any thread. 474 * 475 * @return the string representation of the object on which 476 * the thread is blocked if any; 477 * <tt>null</tt> otherwise. 478 * 479 * @see #getLockInfo 480 */ 481 public String getLockName() { 482 return lockName; 483 } 484 485 /** 486 * Returns the ID of the thread which owns the object 487 * for which the thread associated with this <tt>ThreadInfo</tt> 488 * is blocked waiting. 489 * This method will return <tt>-1</tt> if this thread is not blocked 490 * waiting for any object or if the object is not owned by any thread. 491 * 492 * @return the thread ID of the owner thread of the object 493 * this thread is blocked on; 494 * <tt>-1</tt> if this thread is not blocked 495 * or if the object is not owned by any thread. 496 * 497 * @see #getLockInfo 498 */ 499 public long getLockOwnerId() { 500 return lockOwnerId; 501 } 502 503 /** 504 * Returns the name of the thread which owns the object 505 * for which the thread associated with this <tt>ThreadInfo</tt> 506 * is blocked waiting. 507 * This method will return <tt>null</tt> if this thread is not blocked 508 * waiting for any object or if the object is not owned by any thread. 509 * 510 * @return the name of the thread that owns the object 511 * this thread is blocked on; 512 * <tt>null</tt> if this thread is not blocked 513 * or if the object is not owned by any thread. 514 * 515 * @see #getLockInfo 516 */ 517 public String getLockOwnerName() { 518 return lockOwnerName; 519 } 520 521 /** 522 * Returns the stack trace of the thread 523 * associated with this <tt>ThreadInfo</tt>. 524 * If no stack trace was requested for this thread info, this method 525 * will return a zero-length array. 526 * If the returned array is of non-zero length then the first element of 527 * the array represents the top of the stack, which is the most recent 528 * method invocation in the sequence. The last element of the array 529 * represents the bottom of the stack, which is the least recent method 530 * invocation in the sequence. 531 * 532 * <p>Some Java virtual machines may, under some circumstances, omit one 533 * or more stack frames from the stack trace. In the extreme case, 534 * a virtual machine that has no stack trace information concerning 535 * the thread associated with this <tt>ThreadInfo</tt> 536 * is permitted to return a zero-length array from this method. 537 * 538 * @return an array of <tt>StackTraceElement</tt> objects of the thread. 539 */ 540 public StackTraceElement[] getStackTrace() { 541 return stackTrace; 542 } 543 544 /** 545 * Tests if the thread associated with this <tt>ThreadInfo</tt> 546 * is suspended. This method returns <tt>true</tt> if 547 * {@link Thread#suspend} has been called. 548 * 549 * @return <tt>true</tt> if the thread is suspended; 550 * <tt>false</tt> otherwise. 551 */ 552 public boolean isSuspended() { 553 return suspended; 554 } 555 556 /** 557 * Tests if the thread associated with this <tt>ThreadInfo</tt> 558 * is executing native code via the Java Native Interface (JNI). 559 * The JNI native code does not include 560 * the virtual machine support code or the compiled native 561 * code generated by the virtual machine. 562 * 563 * @return <tt>true</tt> if the thread is executing native code; 564 * <tt>false</tt> otherwise. 565 */ 566 public boolean isInNative() { 567 return inNative; 568 } 569 570 /** 571 * Returns a string representation of this thread info. 572 * The format of this string depends on the implementation. 573 * The returned string will typically include 574 * the {@linkplain #getThreadName thread name}, 575 * the {@linkplain #getThreadId thread ID}, 576 * its {@linkplain #getThreadState state}, 577 * and a {@linkplain #getStackTrace stack trace} if any. 578 * 579 * @return a string representation of this thread info. 580 */ 581 public String toString() { 582 StringBuilder sb = new StringBuilder("\"" + getThreadName() + "\"" + 583 " Id=" + getThreadId() + " " + 584 getThreadState()); 585 if (getLockName() != null) { 586 sb.append(" on " + getLockName()); 587 } 588 if (getLockOwnerName() != null) { 589 sb.append(" owned by \"" + getLockOwnerName() + 590 "\" Id=" + getLockOwnerId()); 591 } 592 if (isSuspended()) { 593 sb.append(" (suspended)"); 594 } 595 if (isInNative()) { 596 sb.append(" (in native)"); 597 } 598 sb.append('\n'); 599 int i = 0; 600 for (; i < stackTrace.length && i < MAX_FRAMES; i++) { 601 StackTraceElement ste = stackTrace[i]; 602 sb.append("\tat " + ste.toString()); 603 sb.append('\n'); 604 if (i == 0 && getLockInfo() != null) { 605 Thread.State ts = getThreadState(); 606 switch (ts) { 607 case BLOCKED: 608 sb.append("\t- blocked on " + getLockInfo()); 609 sb.append('\n'); 610 break; 611 case WAITING: 612 sb.append("\t- waiting on " + getLockInfo()); 613 sb.append('\n'); 614 break; 615 case TIMED_WAITING: 616 sb.append("\t- waiting on " + getLockInfo()); 617 sb.append('\n'); 618 break; 619 default: 620 } 621 } 622 623 for (MonitorInfo mi : lockedMonitors) { 624 if (mi.getLockedStackDepth() == i) { 625 sb.append("\t- locked " + mi); 626 sb.append('\n'); 627 } 628 } 629 } 630 if (i < stackTrace.length) { 631 sb.append("\t..."); 632 sb.append('\n'); 633 } 634 635 LockInfo[] locks = getLockedSynchronizers(); 636 if (locks.length > 0) { 637 sb.append("\n\tNumber of locked synchronizers = " + locks.length); 638 sb.append('\n'); 639 for (LockInfo li : locks) { 640 sb.append("\t- " + li); 641 sb.append('\n'); 642 } 643 } 644 sb.append('\n'); 645 return sb.toString(); 646 } 647 private static final int MAX_FRAMES = 8; 648 649 /** 650 * Returns a <tt>ThreadInfo</tt> object represented by the 651 * given <tt>CompositeData</tt>. 652 * The given <tt>CompositeData</tt> must contain the following attributes 653 * unless otherwise specified below: 654 * <blockquote> 655 * <table border summary="The attributes and their types the given CompositeData contains"> 656 * <tr> 657 * <th align=left>Attribute Name</th> 658 * <th align=left>Type</th> 659 * </tr> 660 * <tr> 661 * <td>threadId</td> 662 * <td><tt>java.lang.Long</tt></td> 663 * </tr> 664 * <tr> 665 * <td>threadName</td> 666 * <td><tt>java.lang.String</tt></td> 667 * </tr> 668 * <tr> 669 * <td>threadState</td> 670 * <td><tt>java.lang.String</tt></td> 671 * </tr> 672 * <tr> 673 * <td>suspended</td> 674 * <td><tt>java.lang.Boolean</tt></td> 675 * </tr> 676 * <tr> 677 * <td>inNative</td> 678 * <td><tt>java.lang.Boolean</tt></td> 679 * </tr> 680 * <tr> 681 * <td>blockedCount</td> 682 * <td><tt>java.lang.Long</tt></td> 683 * </tr> 684 * <tr> 685 * <td>blockedTime</td> 686 * <td><tt>java.lang.Long</tt></td> 687 * </tr> 688 * <tr> 689 * <td>waitedCount</td> 690 * <td><tt>java.lang.Long</tt></td> 691 * </tr> 692 * <tr> 693 * <td>waitedTime</td> 694 * <td><tt>java.lang.Long</tt></td> 695 * </tr> 696 * <tr> 697 * <td>lockInfo</td> 698 * <td><tt>javax.management.openmbean.CompositeData</tt> 699 * - the mapped type for {@link LockInfo} as specified in the 700 * {@link LockInfo#from} method. 701 * <p> 702 * If <tt>cd</tt> does not contain this attribute, 703 * the <tt>LockInfo</tt> object will be constructed from 704 * the value of the <tt>lockName</tt> attribute. </td> 705 * </tr> 706 * <tr> 707 * <td>lockName</td> 708 * <td><tt>java.lang.String</tt></td> 709 * </tr> 710 * <tr> 711 * <td>lockOwnerId</td> 712 * <td><tt>java.lang.Long</tt></td> 713 * </tr> 714 * <tr> 715 * <td>lockOwnerName</td> 716 * <td><tt>java.lang.String</tt></td> 717 * </tr> 718 * <tr> 719 * <td><a name="StackTrace">stackTrace</a></td> 720 * <td><tt>javax.management.openmbean.CompositeData[]</tt> 721 * <p> 722 * Each element is a <tt>CompositeData</tt> representing 723 * StackTraceElement containing the following attributes: 724 * <blockquote> 725 * <table cellspacing=1 cellpadding=0 summary="The attributes and their types the given CompositeData contains"> 726 * <tr> 727 * <th align=left>Attribute Name</th> 728 * <th align=left>Type</th> 729 * </tr> 730 * <tr> 731 * <td>className</td> 732 * <td><tt>java.lang.String</tt></td> 733 * </tr> 734 * <tr> 735 * <td>methodName</td> 736 * <td><tt>java.lang.String</tt></td> 737 * </tr> 738 * <tr> 739 * <td>fileName</td> 740 * <td><tt>java.lang.String</tt></td> 741 * </tr> 742 * <tr> 743 * <td>lineNumber</td> 744 * <td><tt>java.lang.Integer</tt></td> 745 * </tr> 746 * <tr> 747 * <td>nativeMethod</td> 748 * <td><tt>java.lang.Boolean</tt></td> 749 * </tr> 750 * </table> 751 * </blockquote> 752 * </td> 753 * </tr> 754 * <tr> 755 * <td>lockedMonitors</td> 756 * <td><tt>javax.management.openmbean.CompositeData[]</tt> 757 * whose element type is the mapped type for 758 * {@link MonitorInfo} as specified in the 759 * {@link MonitorInfo#from Monitor.from} method. 760 * <p> 761 * If <tt>cd</tt> does not contain this attribute, 762 * this attribute will be set to an empty array. </td> 763 * </tr> 764 * <tr> 765 * <td>lockedSynchronizers</td> 766 * <td><tt>javax.management.openmbean.CompositeData[]</tt> 767 * whose element type is the mapped type for 768 * {@link LockInfo} as specified in the {@link LockInfo#from} method. 769 * <p> 770 * If <tt>cd</tt> does not contain this attribute, 771 * this attribute will be set to an empty array. </td> 772 * </tr> 773 * </table> 774 * </blockquote> 775 * 776 * @param cd <tt>CompositeData</tt> representing a <tt>ThreadInfo</tt> 777 * 778 * @throws IllegalArgumentException if <tt>cd</tt> does not 779 * represent a <tt>ThreadInfo</tt> with the attributes described 780 * above. 781 * 782 * @return a <tt>ThreadInfo</tt> object represented 783 * by <tt>cd</tt> if <tt>cd</tt> is not <tt>null</tt>; 784 * <tt>null</tt> otherwise. 785 */ 786 public static ThreadInfo from(CompositeData cd) { 787 if (cd == null) { 788 return null; 789 } 790 791 if (cd instanceof ThreadInfoCompositeData) { 792 return ((ThreadInfoCompositeData) cd).getThreadInfo(); 793 } else { 794 return new ThreadInfo(cd); 795 } 796 } 797 798 /** 799 * Returns an array of {@link MonitorInfo} objects, each of which 800 * represents an object monitor currently locked by the thread 801 * associated with this <tt>ThreadInfo</tt>. 802 * If no locked monitor was requested for this thread info or 803 * no monitor is locked by the thread, this method 804 * will return a zero-length array. 805 * 806 * @return an array of <tt>MonitorInfo</tt> objects representing 807 * the object monitors locked by the thread. 808 * 809 * @since 1.6 810 */ 811 public MonitorInfo[] getLockedMonitors() { 812 return lockedMonitors; 813 } 814 815 /** 816 * Returns an array of {@link LockInfo} objects, each of which 817 * represents an <a href="LockInfo.html#OwnableSynchronizer">ownable 818 * synchronizer</a> currently locked by the thread associated with 819 * this <tt>ThreadInfo</tt>. If no locked synchronizer was 820 * requested for this thread info or no synchronizer is locked by 821 * the thread, this method will return a zero-length array. 822 * 823 * @return an array of <tt>LockInfo</tt> objects representing 824 * the ownable synchronizers locked by the thread. 825 * 826 * @since 1.6 827 */ 828 public LockInfo[] getLockedSynchronizers() { 829 return lockedSynchronizers; 830 } 831 832 private static final StackTraceElement[] NO_STACK_TRACE = 833 new StackTraceElement[0]; 834 }