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