GNU Classpath (0.95) | |
Frames | No Frames |
1: /* ThreadInfo.java - Information on a thread 2: Copyright (C) 2006 Free Software Foundation 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.lang.management; 39: 40: import java.util.Arrays; 41: 42: import javax.management.openmbean.ArrayType; 43: import javax.management.openmbean.CompositeData; 44: import javax.management.openmbean.CompositeType; 45: import javax.management.openmbean.OpenDataException; 46: import javax.management.openmbean.OpenType; 47: import javax.management.openmbean.SimpleType; 48: 49: /** 50: * <p> 51: * A class which maintains information about a particular 52: * thread. This information includes: 53: * </p> 54: * <ul> 55: * <li><strong>General Thread Information:</strong> 56: * <ul> 57: * <li>The identifier of the thread.</li> 58: * <li>The name of the thread.</li> 59: * </ul> 60: * </li> 61: * <li><strong>Execution Information:</strong> 62: * <ul> 63: * <li>The current state of the thread (e.g. blocked, runnable)</li> 64: * <li>The object upon which the thread is blocked, either because 65: * the thread is waiting to obtain the monitor of that object to enter 66: * one of its synchronized monitor, or because 67: * {@link java.lang.Object#wait()} has been called while the thread 68: * was within a method of that object.</li> 69: * <li>The thread identifier of the current thread holding an object's 70: * monitor, upon which the thread described here is blocked.</li> 71: * <li>The stack trace of the thread (if requested on creation 72: * of this object</li> 73: * <li>The current locks held on object monitors by the thread.</li> 74: * <li>The current locks held on ownable synchronizers by the thread.</li> 75: * </ul> 76: * <li><strong>Synchronization Statistics</strong> 77: * <ul> 78: * <li>The number of times the thread has been blocked waiting for 79: * an object's monitor or in a {@link java.lang.Object#wait()} call.</li> 80: * <li>The accumulated time the thread has been blocked waiting for 81: * an object's monitor on in a {@link java.lang.Object#wait()} call. 82: * The availability of these statistics depends on the virtual machine's 83: * support for thread contention monitoring (see 84: * {@link ThreadMXBean#isThreadContentionMonitoringSupported()}.</li> 85: * </ul> 86: * </li> 87: * </ul> 88: * 89: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 90: * @since 1.5 91: * @see ThreadMXBean#isThreadContentionMonitoringSupported() 92: */ 93: public class ThreadInfo 94: { 95: 96: /** 97: * The id of the thread which this instance concerns. 98: */ 99: private long threadId; 100: 101: /** 102: * The name of the thread which this instance concerns. 103: */ 104: private String threadName; 105: 106: /** 107: * The state of the thread which this instance concerns. 108: */ 109: private Thread.State threadState; 110: 111: /** 112: * The number of times the thread has been blocked. 113: */ 114: private long blockedCount; 115: 116: /** 117: * The accumulated number of milliseconds the thread has 118: * been blocked (used only with thread contention monitoring 119: * support). 120: */ 121: private long blockedTime; 122: 123: /** 124: * The name of the monitor lock on which this thread 125: * is blocked (if any). 126: */ 127: private String lockName; 128: 129: /** 130: * The id of the thread which owns the monitor lock on 131: * which this thread is blocked, or <code>-1</code> 132: * if there is no owner. 133: */ 134: private long lockOwnerId; 135: 136: /** 137: * The name of the thread which owns the monitor lock on 138: * which this thread is blocked, or <code>null</code> 139: * if there is no owner. 140: */ 141: private String lockOwnerName; 142: 143: /** 144: * The number of times the thread has been in a waiting 145: * state. 146: */ 147: private long waitedCount; 148: 149: /** 150: * The accumulated number of milliseconds the thread has 151: * been waiting (used only with thread contention monitoring 152: * support). 153: */ 154: private long waitedTime; 155: 156: /** 157: * True if the thread is in a native method. 158: */ 159: private boolean isInNative; 160: 161: /** 162: * True if the thread is suspended. 163: */ 164: private boolean isSuspended; 165: 166: /** 167: * The stack trace of the thread. 168: */ 169: private StackTraceElement[] trace; 170: 171: /** 172: * The array of information on monitors locked by the thread. 173: */ 174: private MonitorInfo[] lockedMonitors; 175: 176: /** 177: * The array of information on ownable synchronizers locked 178: * by the thread. 179: */ 180: private LockInfo[] lockedSynchronizers; 181: 182: /** 183: * Cache a local reference to the thread management bean. 184: */ 185: private static ThreadMXBean bean = null; 186: 187: /** 188: * Cache the {@link javax.management.openmbean.CompositeType} 189: * for the {@link StackTraceElement}. 190: */ 191: private static CompositeType seType; 192: 193: /** 194: * Constructs a new {@link ThreadInfo} corresponding 195: * to the thread specified. 196: * 197: * @param thread the thread on which the new instance 198: * will be based. 199: * @param blockedCount the number of times the thread 200: * has been blocked. 201: * @param blockedTime the accumulated number of milliseconds 202: * the specified thread has been blocked 203: * (only used with contention monitoring enabled) 204: * @param lock the monitor lock the thread is waiting for 205: * (only used if blocked) 206: * @param lockOwner the thread which owns the monitor lock, or 207: * <code>null</code> if it doesn't have an owner 208: * (only used if blocked) 209: * @param waitedCount the number of times the thread has been in a 210: * waiting state. 211: * @param waitedTime the accumulated number of milliseconds the 212: * specified thread has been waiting 213: * (only used with contention monitoring enabled) 214: * @param isInNative true if the thread is in a native method. 215: * @param isSuspended true if the thread is suspended. 216: * @param trace the stack trace of the thread to a pre-determined 217: * depth (see VMThreadMXBeanImpl) 218: */ 219: private ThreadInfo(Thread thread, long blockedCount, long blockedTime, 220: Object lock, Thread lockOwner, long waitedCount, 221: long waitedTime, boolean isInNative, boolean isSuspended, 222: StackTraceElement[] trace) 223: { 224: this(thread, blockedCount, blockedTime, lock, lockOwner, waitedCount, 225: waitedTime, isInNative, isSuspended, trace, new MonitorInfo[]{}, 226: new LockInfo[]{}); 227: } 228: 229: /** 230: * Constructs a new {@link ThreadInfo} corresponding 231: * to the thread specified. 232: * 233: * @param thread the thread on which the new instance 234: * will be based. 235: * @param blockedCount the number of times the thread 236: * has been blocked. 237: * @param blockedTime the accumulated number of milliseconds 238: * the specified thread has been blocked 239: * (only used with contention monitoring enabled) 240: * @param lock the monitor lock the thread is waiting for 241: * (only used if blocked) 242: * @param lockOwner the thread which owns the monitor lock, or 243: * <code>null</code> if it doesn't have an owner 244: * (only used if blocked) 245: * @param waitedCount the number of times the thread has been in a 246: * waiting state. 247: * @param waitedTime the accumulated number of milliseconds the 248: * specified thread has been waiting 249: * (only used with contention monitoring enabled) 250: * @param isInNative true if the thread is in a native method. 251: * @param isSuspended true if the thread is suspended. 252: * @param trace the stack trace of the thread to a pre-determined 253: * depth (see VMThreadMXBeanImpl) 254: * @param lockedMonitors an array of {@link MonitorInfo} objects 255: * representing locks held on object monitors 256: * by the thread. 257: * @param lockedSynchronizers an array of {@link LockInfo} objects 258: * representing locks held on ownable 259: * synchronizers by the thread. 260: * @since 1.6 261: */ 262: private ThreadInfo(Thread thread, long blockedCount, long blockedTime, 263: Object lock, Thread lockOwner, long waitedCount, 264: long waitedTime, boolean isInNative, boolean isSuspended, 265: StackTraceElement[] trace, MonitorInfo[] lockedMonitors, 266: LockInfo[] lockedSynchronizers) 267: { 268: this(thread.getId(), thread.getName(), thread.getState(), blockedCount, blockedTime, 269: lock == null ? null : lock.getClass().getName() + "@" + 270: Integer.toHexString(System.identityHashCode(lock)), 271: lockOwner == null ? -1 : lockOwner.getId(), 272: lockOwner == null ? null : lockOwner.getName(), 273: waitedCount, waitedTime, isInNative, isSuspended, 274: trace, lockedMonitors, lockedSynchronizers); 275: } 276: 277: /** 278: * Constructs a new {@link ThreadInfo} corresponding 279: * to the thread details specified. 280: * 281: * @param threadId the id of the thread on which this 282: * new instance will be based. 283: * @param threadName the name of the thread on which 284: * this new instance will be based. 285: * @param threadState the state of the thread on which 286: * this new instance will be based. 287: * @param blockedCount the number of times the thread 288: * has been blocked. 289: * @param blockedTime the accumulated number of milliseconds 290: * the specified thread has been blocked 291: * (only used with contention monitoring enabled) 292: * @param lockName the name of the monitor lock the thread is waiting for 293: * (only used if blocked) 294: * @param lockOwnerId the id of the thread which owns the monitor 295: * lock, or <code>-1</code> if it doesn't have an owner 296: * (only used if blocked) 297: * @param lockOwnerName the name of the thread which owns the monitor 298: * lock, or <code>null</code> if it doesn't have an 299: * owner (only used if blocked) 300: * @param waitedCount the number of times the thread has been in a 301: * waiting state. 302: * @param waitedTime the accumulated number of milliseconds the 303: * specified thread has been waiting 304: * (only used with contention monitoring enabled) 305: * @param isInNative true if the thread is in a native method. 306: * @param isSuspended true if the thread is suspended. 307: * @param trace the stack trace of the thread to a pre-determined 308: * depth (see VMThreadMXBeanImpl) 309: */ 310: private ThreadInfo(long threadId, String threadName, Thread.State threadState, 311: long blockedCount, long blockedTime, String lockName, 312: long lockOwnerId, String lockOwnerName, long waitedCount, 313: long waitedTime, boolean isInNative, boolean isSuspended, 314: StackTraceElement[] trace) 315: { 316: this(threadId, threadName, threadState, blockedCount, blockedTime, 317: lockName, lockOwnerId, lockOwnerName, waitedCount, waitedTime, 318: isInNative, isSuspended, trace, new MonitorInfo[]{}, new LockInfo[]{}); 319: } 320: 321: /** 322: * Constructs a new {@link ThreadInfo} corresponding 323: * to the thread details specified. 324: * 325: * @param threadId the id of the thread on which this 326: * new instance will be based. 327: * @param threadName the name of the thread on which 328: * this new instance will be based. 329: * @param threadState the state of the thread on which 330: * this new instance will be based. 331: * @param blockedCount the number of times the thread 332: * has been blocked. 333: * @param blockedTime the accumulated number of milliseconds 334: * the specified thread has been blocked 335: * (only used with contention monitoring enabled) 336: * @param lockName the name of the monitor lock the thread is waiting for 337: * (only used if blocked) 338: * @param lockOwnerId the id of the thread which owns the monitor 339: * lock, or <code>-1</code> if it doesn't have an owner 340: * (only used if blocked) 341: * @param lockOwnerName the name of the thread which owns the monitor 342: * lock, or <code>null</code> if it doesn't have an 343: * owner (only used if blocked) 344: * @param waitedCount the number of times the thread has been in a 345: * waiting state. 346: * @param waitedTime the accumulated number of milliseconds the 347: * specified thread has been waiting 348: * (only used with contention monitoring enabled) 349: * @param isInNative true if the thread is in a native method. 350: * @param isSuspended true if the thread is suspended. 351: * @param trace the stack trace of the thread to a pre-determined 352: * depth (see VMThreadMXBeanImpl) 353: * @param lockedMonitors an array of {@link MonitorInfo} objects 354: * representing locks held on object monitors 355: * by the thread. 356: * @param lockedSynchronizers an array of {@link LockInfo} objects 357: * representing locks held on ownable 358: * synchronizers by the thread. 359: * 360: * @since 1.6 361: */ 362: private ThreadInfo(long threadId, String threadName, Thread.State threadState, 363: long blockedCount, long blockedTime, String lockName, 364: long lockOwnerId, String lockOwnerName, long waitedCount, 365: long waitedTime, boolean isInNative, boolean isSuspended, 366: StackTraceElement[] trace, MonitorInfo[] lockedMonitors, 367: LockInfo[] lockedSynchronizers) 368: { 369: this.threadId = threadId; 370: this.threadName = threadName; 371: this.threadState = threadState; 372: this.blockedCount = blockedCount; 373: this.blockedTime = blockedTime; 374: this.lockName = lockName; 375: this.lockOwnerId = lockOwnerId; 376: this.lockOwnerName = lockOwnerName; 377: this.waitedCount = waitedCount; 378: this.waitedTime = waitedTime; 379: this.isInNative = isInNative; 380: this.isSuspended = isSuspended; 381: this.trace = trace; 382: this.lockedMonitors = lockedMonitors; 383: this.lockedSynchronizers = lockedSynchronizers; 384: } 385: 386: /** 387: * Checks for an attribute in a {@link CompositeData} structure 388: * with the correct type. 389: * 390: * @param ctype the composite data type to check. 391: * @param name the name of the attribute. 392: * @param type the type to check for. 393: * @throws IllegalArgumentException if the attribute is absent 394: * or of the wrong type. 395: */ 396: static void checkAttribute(CompositeType ctype, String name, 397: OpenType type) 398: throws IllegalArgumentException 399: { 400: OpenType foundType = ctype.getType(name); 401: if (foundType == null) 402: throw new IllegalArgumentException("Could not find a field named " + 403: name); 404: if (!(foundType.equals(type))) 405: throw new IllegalArgumentException("Field " + name + " is not of " + 406: "type " + type.getClassName()); 407: } 408: 409: /** 410: * Returns the {@link javax.management.openmbean.CompositeType} for 411: * a {@link StackTraceElement}. 412: * 413: * @return the type for the stack trace element. 414: */ 415: static CompositeType getStackTraceType() 416: { 417: if (seType == null) 418: try 419: { 420: seType = new CompositeType(StackTraceElement.class.getName(), 421: "An element of a stack trace", 422: new String[] { "className", "methodName", 423: "fileName", "lineNumber", 424: "nativeMethod" 425: }, 426: new String[] { "Name of the class", 427: "Name of the method", 428: "Name of the source code file", 429: "Line number", 430: "True if this is a native method" 431: }, 432: new OpenType[] { 433: SimpleType.STRING, SimpleType.STRING, 434: SimpleType.STRING, SimpleType.INTEGER, 435: SimpleType.BOOLEAN 436: }); 437: } 438: catch (OpenDataException e) 439: { 440: throw new IllegalStateException("Something went wrong in creating " + 441: "the composite data type for the " + 442: "stack trace element.", e); 443: } 444: return seType; 445: } 446: 447: /** 448: * <p> 449: * Returns a {@link ThreadInfo} instance using the values 450: * given in the supplied 451: * {@link javax.management.openmbean.CompositeData} object. 452: * The composite data instance should contain the following 453: * attributes with the specified types: 454: * </p> 455: * <table> 456: * <th><td>Name</td><td>Type</td></th> 457: * <tr><td>threadId</td><td>java.lang.Long</td></tr> 458: * <tr><td>threadName</td><td>java.lang.String</td></tr> 459: * <tr><td>threadState</td><td>java.lang.String</td></tr> 460: * <tr><td>suspended</td><td>java.lang.Boolean</td></tr> 461: * <tr><td>inNative</td><td>java.lang.Boolean</td></tr> 462: * <tr><td>blockedCount</td><td>java.lang.Long</td></tr> 463: * <tr><td>blockedTime</td><td>java.lang.Long</td></tr> 464: * <tr><td>waitedCount</td><td>java.lang.Long</td></tr> 465: * <tr><td>waitedTime</td><td>java.lang.Long</td></tr> 466: * <tr><td>lockName</td><td>java.lang.String</td></tr> 467: * <tr><td>lockOwnerId</td><td>java.lang.Long</td></tr> 468: * <tr><td>lockOwnerName</td><td>java.lang.String</td></tr> 469: * <tr><td>stackTrace</td><td>javax.management.openmbean.CompositeData[] 470: * </td></tr> 471: * </table> 472: * <p> 473: * The stack trace is further described as: 474: * </p> 475: * <table> 476: * <th><td>Name</td><td>Type</td></th> 477: * <tr><td>className</td><td>java.lang.String</td></tr> 478: * <tr><td>methodName</td><td>java.lang.String</td></tr> 479: * <tr><td>fileName</td><td>java.lang.String</td></tr> 480: * <tr><td>lineNumber</td><td>java.lang.Integer</td></tr> 481: * <tr><td>nativeMethod</td><td>java.lang.Boolean</td></tr> 482: * </table> 483: * 484: * @param data the composite data structure to take values from. 485: * @return a new instance containing the values from the 486: * composite data structure, or <code>null</code> 487: * if the data structure was also <code>null</code>. 488: * @throws IllegalArgumentException if the composite data structure 489: * does not match the structure 490: * outlined above. 491: */ 492: public static ThreadInfo from(CompositeData data) 493: { 494: if (data == null) 495: return null; 496: CompositeType type = data.getCompositeType(); 497: checkAttribute(type, "ThreadId", SimpleType.LONG); 498: checkAttribute(type, "ThreadName", SimpleType.STRING); 499: checkAttribute(type, "ThreadState", SimpleType.STRING); 500: checkAttribute(type, "Suspended", SimpleType.BOOLEAN); 501: checkAttribute(type, "InNative", SimpleType.BOOLEAN); 502: checkAttribute(type, "BlockedCount", SimpleType.LONG); 503: checkAttribute(type, "BlockedTime", SimpleType.LONG); 504: checkAttribute(type, "WaitedCount", SimpleType.LONG); 505: checkAttribute(type, "WaitedTime", SimpleType.LONG); 506: checkAttribute(type, "LockName", SimpleType.STRING); 507: checkAttribute(type, "LockOwnerId", SimpleType.LONG); 508: checkAttribute(type, "LockOwnerName", SimpleType.STRING); 509: try 510: { 511: checkAttribute(type, "StackTrace", 512: new ArrayType(1, getStackTraceType())); 513: } 514: catch (OpenDataException e) 515: { 516: throw new IllegalStateException("Something went wrong in creating " + 517: "the array for the stack trace element.", 518: e); 519: } 520: OpenType foundType = type.getType("LockedMonitors"); 521: if (foundType != null) 522: try 523: { 524: CompositeType mType = new CompositeType(MonitorInfo.class.getName(), 525: "Information on a object monitor lock", 526: new String[] { "ClassName", 527: "IdentityHashCode", 528: "LockedStackDepth", 529: "LockedStackFrame" 530: }, 531: new String[] { "Name of the class", 532: "Identity hash code " + 533: "of the class", 534: "Stack depth at time " + 535: "of lock", 536: "Stack frame at time " + 537: "of lock", 538: }, 539: new OpenType[] { 540: SimpleType.STRING, SimpleType.INTEGER, 541: SimpleType.INTEGER, getStackTraceType() 542: }); 543: if (!(foundType.equals(new ArrayType(1, mType)))) 544: throw new IllegalArgumentException("Field LockedMonitors is not of " + 545: "type " + mType.getClassName()); 546: } 547: catch (OpenDataException e) 548: { 549: throw new IllegalStateException("Something went wrong in creating " + 550: "the composite data type for the " + 551: "object monitor information array.", e); 552: } 553: foundType = type.getType("LockedSynchronizers"); 554: if (foundType != null) 555: try 556: { 557: CompositeType lType = new CompositeType(LockInfo.class.getName(), 558: "Information on a lock", 559: new String[] { "ClassName", 560: "IdentityHashCode" 561: }, 562: new String[] { "Name of the class", 563: "Identity hash code " + 564: "of the class" 565: }, 566: new OpenType[] { 567: SimpleType.STRING, SimpleType.INTEGER 568: }); 569: if (!(foundType.equals(new ArrayType(1, lType)))) 570: throw new IllegalArgumentException("Field LockedSynchronizers is not of " + 571: "type " + lType.getClassName()); 572: } 573: catch (OpenDataException e) 574: { 575: throw new IllegalStateException("Something went wrong in creating " + 576: "the composite data type for the " + 577: "ownable synchronizerinformation array.", e); 578: } 579: CompositeData[] dTraces = (CompositeData[]) data.get("StackTrace"); 580: StackTraceElement[] traces = new StackTraceElement[dTraces.length]; 581: for (int a = 0; a < dTraces.length; ++a) 582: /* FIXME: We can't use the boolean as there is no available 583: constructor. */ 584: traces[a] = 585: new StackTraceElement((String) dTraces[a].get("ClassName"), 586: (String) dTraces[a].get("MethodName"), 587: (String) dTraces[a].get("FileName"), 588: ((Integer) 589: dTraces[a].get("LineNumber")).intValue()); 590: MonitorInfo[] mInfo; 591: if (data.containsKey("LockedMonitors")) 592: { 593: CompositeData[] dmInfos = (CompositeData[]) data.get("LockedMonitors"); 594: mInfo = new MonitorInfo[dmInfos.length]; 595: for (int a = 0; a < dmInfos.length; ++a) 596: mInfo[a] = MonitorInfo.from(dmInfos[a]); 597: } 598: else 599: mInfo = new MonitorInfo[]{}; 600: LockInfo[] lInfo; 601: if (data.containsKey("LockedSynchronizers")) 602: { 603: CompositeData[] dlInfos = (CompositeData[]) data.get("LockedSynchronizers"); 604: lInfo = new LockInfo[dlInfos.length]; 605: for (int a = 0; a < dlInfos.length; ++a) 606: lInfo[a] = new LockInfo((String) dlInfos[a].get("ClassName"), 607: (Integer) dlInfos[a].get("IdentityHashCode")); 608: } 609: else 610: lInfo = new LockInfo[]{}; 611: return new ThreadInfo(((Long) data.get("ThreadId")).longValue(), 612: (String) data.get("ThreadName"), 613: Thread.State.valueOf((String) data.get("ThreadState")), 614: ((Long) data.get("BlockedCount")).longValue(), 615: ((Long) data.get("BlockedTime")).longValue(), 616: (String) data.get("LockName"), 617: ((Long) data.get("LockOwnerId")).longValue(), 618: (String) data.get("LockOwnerName"), 619: ((Long) data.get("WaitedCount")).longValue(), 620: ((Long) data.get("WaitedTime")).longValue(), 621: ((Boolean) data.get("InNative")).booleanValue(), 622: ((Boolean) data.get("Suspended")).booleanValue(), 623: traces, mInfo, lInfo); 624: } 625: 626: /** 627: * Returns the number of times this thread has been 628: * in the {@link java.lang.Thread.State#BLOCKED} state. 629: * A thread enters this state when it is waiting to 630: * obtain an object's monitor. This may occur either 631: * on entering a synchronized method for the first time, 632: * or on re-entering it following a call to 633: * {@link java.lang.Object#wait()}. 634: * 635: * @return the number of times this thread has been blocked. 636: */ 637: public long getBlockedCount() 638: { 639: return blockedCount; 640: } 641: 642: /** 643: * <p> 644: * Returns the accumulated number of milliseconds this 645: * thread has been in the 646: * {@link java.lang.Thread.State#BLOCKED} state 647: * since thread contention monitoring was last enabled. 648: * A thread enters this state when it is waiting to 649: * obtain an object's monitor. This may occur either 650: * on entering a synchronized method for the first time, 651: * or on re-entering it following a call to 652: * {@link java.lang.Object#wait()}. 653: * </p> 654: * <p> 655: * Use of this method requires virtual machine support 656: * for thread contention monitoring and for this support 657: * to be enabled. 658: * </p> 659: * 660: * @return the accumulated time (in milliseconds) that this 661: * thread has spent in the blocked state, since 662: * thread contention monitoring was enabled, or -1 663: * if thread contention monitoring is disabled. 664: * @throws UnsupportedOperationException if the virtual 665: * machine does not 666: * support contention 667: * monitoring. 668: * @see ThreadMXBean#isThreadContentionMonitoringEnabled() 669: * @see ThreadMXBean#isThreadContentionMonitoringSupported() 670: */ 671: public long getBlockedTime() 672: { 673: if (bean == null) 674: bean = ManagementFactory.getThreadMXBean(); 675: // Will throw UnsupportedOperationException for us 676: if (bean.isThreadContentionMonitoringEnabled()) 677: return blockedTime; 678: else 679: return -1; 680: } 681: 682: /** 683: * Returns an array of {@link MonitorInfo} objects representing 684: * information on the locks on object monitors held by the thread. 685: * If no locks are held, or such information was not requested 686: * on creating this {@link ThreadInfo} object, a zero-length 687: * array will be returned. 688: * 689: * @return information on object monitors locked by this thread. 690: */ 691: public MonitorInfo[] getLockedMonitors() 692: { 693: return lockedMonitors; 694: } 695: 696: /** 697: * Returns an array of {@link LockInfo} objects representing 698: * information on the locks on ownable synchronizers held by the thread. 699: * If no locks are held, or such information was not requested 700: * on creating this {@link ThreadInfo} object, a zero-length 701: * array will be returned. 702: * 703: * @return information on ownable synchronizers locked by this thread. 704: */ 705: public LockInfo[] getLockedSynchronizers() 706: { 707: return lockedSynchronizers; 708: } 709: 710: /** 711: * <p> 712: * Returns a {@link LockInfo} object representing the 713: * lock on which this thread is blocked. If the thread 714: * is not blocked, this method returns <code>null</code>. 715: * </p> 716: * <p> 717: * The thread may be blocked due to one of three reasons: 718: * </p> 719: * <ol> 720: * <li>The thread is in the <code>BLOCKED</code> state 721: * waiting to acquire an object monitor in order to enter 722: * a synchronized method or block.</li> 723: * <li>The thread is in the <code>WAITING</code> or 724: * <code>TIMED_WAITING</code> state due to a call to 725: * {@link java.lang.Object#wait()}.</li> 726: * <li>The thread is in the <code>WAITING</code> or 727: * <code>TIMED_WAITING</code> state due to a call 728: * to {@link java.util.concurrent.locks.LockSupport#park()}. 729: * The lock is the return value of 730: * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li> 731: * </ol> 732: * 733: * @return a {@link LockInfo} object representing the lock on 734: * which the thread is blocked, or <code>null</code> if 735: * the thread isn't blocked. 736: * @since 1.6 737: * @see #getLockName() 738: */ 739: public LockInfo getLockInfo() 740: { 741: String lockName = getLockName(); 742: int at = lockName.indexOf('@'); 743: return new LockInfo(lockName.substring(0, at), 744: Integer.decode(lockName.substring(at + 1))); 745: } 746: 747: /** 748: * <p> 749: * Returns a {@link java.lang.String} representation of 750: * the lock on which this thread is blocked. If 751: * the thread is not blocked, this method returns 752: * <code>null</code>. 753: * </p> 754: * <p> 755: * The returned {@link java.lang.String} is constructed 756: * using the class name and identity hashcode (usually 757: * the memory address of the object) of the lock. The 758: * two are separated by the '@' character, and the identity 759: * hashcode is represented in hexadecimal. Thus, for a 760: * lock, <code>l</code>, the returned value is 761: * the result of concatenating 762: * <code>l.getClass().getName()</code>, <code>"@"</code> 763: * and 764: * <code>Integer.toHexString(System.identityHashCode(l))</code>. 765: * The value is only unique to the extent that the identity 766: * hash code is also unique. The value is the same as would 767: * be returned by <code>getLockInfo().toString()</code> 768: * </p> 769: * 770: * @return a string representing the lock on which this 771: * thread is blocked, or <code>null</code> if 772: * the thread is not blocked. 773: */ 774: public String getLockName() 775: { 776: if (!isThreadBlocked()) 777: return null; 778: return lockName; 779: } 780: 781: /** 782: * Returns the identifier of the thread which owns the 783: * monitor lock this thread is waiting for. -1 is returned 784: * if either this thread is not blocked, or the lock is 785: * not held by any other thread. 786: * 787: * @return the thread identifier of thread holding the lock 788: * this thread is waiting for, or -1 if the thread 789: * is not blocked or the lock is not held by another 790: * thread. 791: */ 792: public long getLockOwnerId() 793: { 794: if (!isThreadBlocked()) 795: return -1; 796: return lockOwnerId; 797: } 798: 799: /** 800: * Returns the name of the thread which owns the 801: * monitor lock this thread is waiting for. <code>null</code> 802: * is returned if either this thread is not blocked, 803: * or the lock is not held by any other thread. 804: * 805: * @return the thread identifier of thread holding the lock 806: * this thread is waiting for, or <code>null</code> 807: * if the thread is not blocked or the lock is not 808: * held by another thread. 809: */ 810: public String getLockOwnerName() 811: { 812: if (!isThreadBlocked()) 813: return null; 814: return lockOwnerName; 815: } 816: 817: /** 818: * <p> 819: * Returns the stack trace of this thread to the depth 820: * specified on creation of this {@link ThreadInfo} 821: * object. If the depth is zero, an empty array will 822: * be returned. For non-zero arrays, the elements 823: * start with the most recent trace at position zero. 824: * The bottom of the stack represents the oldest method 825: * invocation which meets the depth requirements. 826: * </p> 827: * <p> 828: * Some virtual machines may not be able to return 829: * stack trace information for a thread. In these 830: * cases, an empty array will also be returned. 831: * </p> 832: * 833: * @return an array of {@link java.lang.StackTraceElement}s 834: * representing the trace of this thread. 835: */ 836: public StackTraceElement[] getStackTrace() 837: { 838: return trace; 839: } 840: 841: /** 842: * Returns the identifier of the thread associated with 843: * this instance of {@link ThreadInfo}. 844: * 845: * @return the thread's identifier. 846: */ 847: public long getThreadId() 848: { 849: return threadId; 850: } 851: 852: /** 853: * Returns the name of the thread associated with 854: * this instance of {@link ThreadInfo}. 855: * 856: * @return the thread's name. 857: */ 858: public String getThreadName() 859: { 860: return threadName; 861: } 862: 863: /** 864: * Returns the state of the thread associated with 865: * this instance of {@link ThreadInfo}. 866: * 867: * @return the thread's state. 868: */ 869: public Thread.State getThreadState() 870: { 871: return threadState; 872: } 873: 874: /** 875: * Returns the number of times this thread has been 876: * in the {@link java.lang.Thread.State#WAITING} 877: * or {@link java.lang.Thread.State#TIMED_WAITING} state. 878: * A thread enters one of these states when it is waiting 879: * due to a call to {@link java.lang.Object.wait()}, 880: * {@link java.lang.Object.join()} or 881: * {@link java.lang.concurrent.locks.LockSupport.park()}, 882: * either with an infinite or timed delay, respectively. 883: * 884: * @return the number of times this thread has been waiting. 885: */ 886: public long getWaitedCount() 887: { 888: return waitedCount; 889: } 890: 891: /** 892: * <p> 893: * Returns the accumulated number of milliseconds this 894: * thread has been in the 895: * {@link java.lang.Thread.State#WAITING} or 896: * {@link java.lang.Thread.State#TIMED_WAITING} state, 897: * since thread contention monitoring was last enabled. 898: * A thread enters one of these states when it is waiting 899: * due to a call to {@link java.lang.Object.wait()}, 900: * {@link java.lang.Object.join()} or 901: * {@link java.lang.concurrent.locks.LockSupport.park()}, 902: * either with an infinite or timed delay, respectively. 903: * </p> 904: * <p> 905: * Use of this method requires virtual machine support 906: * for thread contention monitoring and for this support 907: * to be enabled. 908: * </p> 909: * 910: * @return the accumulated time (in milliseconds) that this 911: * thread has spent in one of the waiting states, since 912: * thread contention monitoring was enabled, or -1 913: * if thread contention monitoring is disabled. 914: * @throws UnsupportedOperationException if the virtual 915: * machine does not 916: * support contention 917: * monitoring. 918: * @see ThreadMXBean#isThreadContentionMonitoringEnabled() 919: * @see ThreadMXBean#isThreadContentionMonitoringSupported() 920: */ 921: public long getWaitedTime() 922: { 923: if (bean == null) 924: bean = ManagementFactory.getThreadMXBean(); 925: // Will throw UnsupportedOperationException for us 926: if (bean.isThreadContentionMonitoringEnabled()) 927: return waitedTime; 928: else 929: return -1; 930: } 931: 932: /** 933: * Returns true if the thread is in a native method. This 934: * excludes native code which forms part of the virtual 935: * machine itself, or which results from Just-In-Time 936: * compilation. 937: * 938: * @return true if the thread is in a native method, false 939: * otherwise. 940: */ 941: public boolean isInNative() 942: { 943: return isInNative; 944: } 945: 946: /** 947: * Returns true if the thread has been suspended using 948: * {@link java.lang.Thread#suspend()}. 949: * 950: * @return true if the thread is suspended, false otherwise. 951: */ 952: public boolean isSuspended() 953: { 954: return isSuspended; 955: } 956: 957: /** 958: * Returns a {@link java.lang.String} representation of 959: * this {@link ThreadInfo} object. This takes the form 960: * <code>java.lang.management.ThreadInfo[id=tid, name=n, 961: * state=s, blockedCount=bc, waitedCount=wc, isInNative=iin, 962: * isSuspended=is]</code>, where <code>tid</code> is 963: * the thread identifier, <code>n</code> is the 964: * thread name, <code>s</code> is the thread state, 965: * <code>bc</code> is the blocked state count, 966: * <code>wc</code> is the waiting state count and 967: * <code>iin</code> and <code>is</code> are boolean 968: * flags to indicate the thread is in native code or 969: * suspended respectively. If the thread is blocked, 970: * <code>lock=l, lockOwner=lo</code> is also included, 971: * where <code>l</code> is the lock waited for, and 972: * <code>lo</code> is the thread which owns the lock 973: * (or null if there is no owner). 974: * 975: * @return the string specified above. 976: */ 977: public String toString() 978: { 979: return getClass().getName() + 980: "[id=" + threadId + 981: ", name=" + threadName + 982: ", state=" + threadState + 983: ", blockedCount=" + blockedCount + 984: ", waitedCount=" + waitedCount + 985: ", isInNative=" + isInNative + 986: ", isSuspended=" + isSuspended + 987: (isThreadBlocked() ? 988: ", lockOwnerId=" + lockOwnerId + 989: ", lockOwnerName=" + lockOwnerName : "") + 990: ", lockedMonitors=" + Arrays.toString(lockedMonitors) + 991: ", lockedSynchronizers=" + Arrays.toString(lockedSynchronizers) + 992: "]"; 993: } 994: 995: /** 996: * <p> 997: * Returns true if the thread is in a blocked state. 998: * The thread is regarded as blocked if: 999: * </p> 1000: * <ol> 1001: * <li>The thread is in the <code>BLOCKED</code> state 1002: * waiting to acquire an object monitor in order to enter 1003: * a synchronized method or block.</li> 1004: * <li>The thread is in the <code>WAITING</code> or 1005: * <code>TIMED_WAITING</code> state due to a call to 1006: * {@link java.lang.Object#wait()}.</li> 1007: * <li>The thread is in the <code>WAITING</code> or 1008: * <code>TIMED_WAITING</code> state due to a call 1009: * to {@link java.util.concurrent.locks.LockSupport#park()}. 1010: * The lock is the return value of 1011: * {@link java.util.concurrent.locks.LockSupport#getBlocker()}.</li> 1012: * </ol> 1013: * 1014: * @return true if the thread is blocked. 1015: */ 1016: private boolean isThreadBlocked() 1017: { 1018: return (threadState == Thread.State.BLOCKED || 1019: threadState == Thread.State.WAITING || 1020: threadState == Thread.State.TIMED_WAITING); 1021: } 1022: 1023: }
GNU Classpath (0.95) |