Source for java.lang.management.ThreadInfo

   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 javax.management.openmbean.ArrayType;
  41: import javax.management.openmbean.CompositeData;
  42: import javax.management.openmbean.CompositeType;
  43: import javax.management.openmbean.OpenDataException;
  44: import javax.management.openmbean.OpenType;
  45: import javax.management.openmbean.SimpleType;
  46: 
  47: /**
  48:  * <p>
  49:  * A class which maintains information about a particular
  50:  * thread.  This information includes:
  51:  * </p>
  52:  * <ul>
  53:  * <li><strong>General Thread Information:</strong>
  54:  * <ul>
  55:  * <li>The identifier of the thread.</li>
  56:  * <li>The name of the thread.</li>
  57:  * </ul>
  58:  * </li>
  59:  * <li><strong>Execution Information:</strong>
  60:  * <ul>
  61:  * <li>The current state of the thread (e.g. blocked, runnable)</li>
  62:  * <li>The object upon which the thread is blocked, either because
  63:  * the thread is waiting to obtain the monitor of that object to enter
  64:  * one of its synchronized monitor, or because
  65:  * {@link java.lang.Object#wait()} has been called while the thread
  66:  * was within a method of that object.</li>
  67:  * <li>The thread identifier of the current thread holding an object's
  68:  * monitor, upon which the thread described here is blocked.</li>
  69:  * <li>The stack trace of the thread (if requested on creation
  70:  * of this object</li>
  71:  * </ul>
  72:  * <li><strong>Synchronization Statistics</strong>
  73:  * <ul>
  74:  * <li>The number of times the thread has been blocked waiting for
  75:  * an object's monitor or in a {@link java.lang.Object#wait()} call.</li>
  76:  * <li>The accumulated time the thread has been blocked waiting for
  77:  * an object's monitor on in a {@link java.lang.Object#wait()} call.
  78:  * The availability of these statistics depends on the virtual machine's
  79:  * support for thread contention monitoring (see
  80:  * {@link ThreadMXBean#isThreadContentionMonitoringSupported()}.</li>
  81:  * </ul>
  82:  * </li>
  83:  * </ul>
  84:  *
  85:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  86:  * @since 1.5
  87:  * @see ThreadMXBean#isThreadContentionMonitoringSupported()
  88:  */
  89: public class ThreadInfo
  90: {
  91: 
  92:   /**
  93:    * The id of the thread which this instance concerns.
  94:    */
  95:   private long threadId;
  96: 
  97:   /**
  98:    * The name of the thread which this instance concerns.
  99:    */
 100:   private String threadName;
 101: 
 102:   /**
 103:    * The state of the thread which this instance concerns.
 104:    */
 105:   private String threadState;
 106: 
 107:   /**
 108:    * The number of times the thread has been blocked.
 109:    */
 110:   private long blockedCount;
 111: 
 112:   /**
 113:    * The accumulated number of milliseconds the thread has
 114:    * been blocked (used only with thread contention monitoring
 115:    * support).
 116:    */
 117:   private long blockedTime;
 118: 
 119:   /**
 120:    * The name of the monitor lock on which this thread
 121:    * is blocked (if any).
 122:    */
 123:   private String lockName;
 124: 
 125:   /**
 126:    * The id of the thread which owns the monitor lock on
 127:    * which this thread is blocked, or <code>-1</code>
 128:    * if there is no owner.
 129:    */
 130:   private long lockOwnerId;
 131: 
 132:   /**
 133:    * The name of the thread which owns the monitor lock on
 134:    * which this thread is blocked, or <code>null</code>
 135:    * if there is no owner.
 136:    */
 137:   private String lockOwnerName;
 138: 
 139:   /**
 140:    * The number of times the thread has been in a waiting
 141:    * state.
 142:    */
 143:   private long waitedCount;
 144: 
 145:   /**
 146:    * The accumulated number of milliseconds the thread has
 147:    * been waiting (used only with thread contention monitoring
 148:    * support).
 149:    */
 150:   private long waitedTime;
 151: 
 152:   /**
 153:    * True if the thread is in a native method.
 154:    */
 155:   private boolean isInNative;
 156: 
 157:   /**
 158:    * True if the thread is suspended.
 159:    */
 160:   private boolean isSuspended;
 161: 
 162:   /**
 163:    * The stack trace of the thread.
 164:    */
 165:   private StackTraceElement[] trace;
 166: 
 167:   /**
 168:    * Cache a local reference to the thread management bean.
 169:    */
 170:   private static ThreadMXBean bean = null;
 171: 
 172:   /**
 173:    * Constructs a new {@link ThreadInfo} corresponding
 174:    * to the thread specified.
 175:    *
 176:    * @param thread the thread on which the new instance
 177:    *               will be based.
 178:    * @param blockedCount the number of times the thread
 179:    *                     has been blocked.
 180:    * @param blockedTime the accumulated number of milliseconds
 181:    *                    the specified thread has been blocked
 182:    *                    (only used with contention monitoring enabled)
 183:    * @param lock the monitor lock the thread is waiting for
 184:    *             (only used if blocked)
 185:    * @param lockOwner the thread which owns the monitor lock, or
 186:    *                  <code>null</code> if it doesn't have an owner
 187:    *                  (only used if blocked)
 188:    * @param waitedCount the number of times the thread has been in a
 189:    *                    waiting state.
 190:    * @param waitedTime the accumulated number of milliseconds the
 191:    *                   specified thread has been waiting
 192:    *                   (only used with contention monitoring enabled)
 193:    * @param isInNative true if the thread is in a native method.
 194:    * @param isSuspended true if the thread is suspended.
 195:    * @param trace the stack trace of the thread to a pre-determined
 196:    *              depth (see VMThreadMXBeanImpl)
 197:    */
 198:   private ThreadInfo(Thread thread, long blockedCount, long blockedTime,
 199:              Object lock, Thread lockOwner, long waitedCount,
 200:              long waitedTime, boolean isInNative, boolean isSuspended,
 201:              StackTraceElement[] trace)
 202:   {
 203:     this(thread.getId(), thread.getName(), thread.getState(), blockedCount,
 204:      blockedTime, lock.getClass().getName() + "@" + 
 205:      Integer.toHexString(System.identityHashCode(lock)), lockOwner.getId(),
 206:      lockOwner.getName(), waitedCount, waitedTime, isInNative, isSuspended,
 207:      trace);
 208:   }
 209: 
 210:   /**
 211:    * Constructs a new {@link ThreadInfo} corresponding
 212:    * to the thread details specified.
 213:    *
 214:    * @param threadId the id of the thread on which this
 215:    *                 new instance will be based.
 216:    * @param threadName the name of the thread on which
 217:    *                 this new instance will be based.
 218:    * @param threadState the state of the thread on which
 219:    *                 this new instance will be based.
 220:    * @param blockedCount the number of times the thread
 221:    *                     has been blocked.
 222:    * @param blockedTime the accumulated number of milliseconds
 223:    *                    the specified thread has been blocked
 224:    *                    (only used with contention monitoring enabled)
 225:    * @param lockName the name of the monitor lock the thread is waiting for
 226:    *                 (only used if blocked)
 227:    * @param lockOwnerId the id of the thread which owns the monitor
 228:    *                  lock, or <code>-1</code> if it doesn't have an owner
 229:    *                  (only used if blocked)
 230:    * @param lockOwnerName the name of the thread which owns the monitor
 231:    *                  lock, or <code>null</code> if it doesn't have an 
 232:    *                  owner (only used if blocked)
 233:    * @param waitedCount the number of times the thread has been in a
 234:    *                    waiting state.
 235:    * @param waitedTime the accumulated number of milliseconds the
 236:    *                   specified thread has been waiting
 237:    *                   (only used with contention monitoring enabled)
 238:    * @param isInNative true if the thread is in a native method.
 239:    * @param isSuspended true if the thread is suspended.
 240:    * @param trace the stack trace of the thread to a pre-determined
 241:    *              depth (see VMThreadMXBeanImpl)
 242:    */
 243:   private ThreadInfo(long threadId, String threadName, String threadState,
 244:              long blockedCount, long blockedTime, String lockName, 
 245:              long lockOwnerId, String lockOwnerName, long waitedCount,
 246:              long waitedTime, boolean isInNative, boolean isSuspended,
 247:              StackTraceElement[] trace)
 248:   {
 249:     this.threadId = threadId;
 250:     this.threadName = threadName;
 251:     this.threadState = threadState;
 252:     this.blockedCount = blockedCount;
 253:     this.blockedTime = blockedTime;
 254:     this.lockName = lockName;
 255:     this.lockOwnerId = lockOwnerId;
 256:     this.lockOwnerName = lockOwnerName;
 257:     this.waitedCount = waitedCount;
 258:     this.waitedTime = waitedTime;
 259:     this.isInNative = isInNative;
 260:     this.isSuspended = isSuspended;
 261:     this.trace = trace;
 262:   }
 263: 
 264:   /**
 265:    * Checks for an attribute in a {@link CompositeData} structure
 266:    * with the correct type.
 267:    *
 268:    * @param ctype the composite data type to check.
 269:    * @param name the name of the attribute.
 270:    * @param type the type to check for.
 271:    * @throws IllegalArgumentException if the attribute is absent
 272:    *                                  or of the wrong type.
 273:    */
 274:   static void checkAttribute(CompositeType ctype, String name,
 275:                  OpenType type)
 276:     throws IllegalArgumentException
 277:   {
 278:     OpenType foundType = ctype.getType(name);
 279:     if (foundType == null)
 280:       throw new IllegalArgumentException("Could not find a field named " +
 281:                      name);
 282:     if (!(foundType.equals(type)))
 283:       throw new IllegalArgumentException("Field " + name + " is not of " +
 284:                      "type " + type.getClassName());
 285:   }
 286: 
 287:   /**
 288:    * <p>
 289:    * Returns a {@link ThreadInfo} instance using the values
 290:    * given in the supplied
 291:    * {@link javax.management.openmbean.CompositeData} object.
 292:    * The composite data instance should contain the following
 293:    * attributes with the specified types:
 294:    * </p>
 295:    * <table>
 296:    * <th><td>Name</td><td>Type</td></th>
 297:    * <tr><td>threadId</td><td>java.lang.Long</td></tr>
 298:    * <tr><td>threadName</td><td>java.lang.String</td></tr>
 299:    * <tr><td>threadState</td><td>java.lang.String</td></tr>
 300:    * <tr><td>suspended</td><td>java.lang.Boolean</td></tr>
 301:    * <tr><td>inNative</td><td>java.lang.Boolean</td></tr>
 302:    * <tr><td>blockedCount</td><td>java.lang.Long</td></tr>
 303:    * <tr><td>blockedTime</td><td>java.lang.Long</td></tr>
 304:    * <tr><td>waitedCount</td><td>java.lang.Long</td></tr>
 305:    * <tr><td>waitedTime</td><td>java.lang.Long</td></tr>
 306:    * <tr><td>lockName</td><td>java.lang.String</td></tr>
 307:    * <tr><td>lockOwnerId</td><td>java.lang.Long</td></tr>
 308:    * <tr><td>lockOwnerName</td><td>java.lang.String</td></tr>
 309:    * <tr><td>stackTrace</td><td>javax.management.openmbean.CompositeData[]
 310:    * </td></tr>
 311:    * </table>
 312:    * <p>
 313:    * The stack trace is further described as:
 314:    * </p>
 315:    * <table>
 316:    * <th><td>Name</td><td>Type</td></th>
 317:    * <tr><td>className</td><td>java.lang.String</td></tr>
 318:    * <tr><td>methodName</td><td>java.lang.String</td></tr>
 319:    * <tr><td>fileName</td><td>java.lang.String</td></tr>
 320:    * <tr><td>lineNumber</td><td>java.lang.Integer</td></tr>
 321:    * <tr><td>nativeMethod</td><td>java.lang.Boolean</td></tr>
 322:    * </table>
 323:    * 
 324:    * @param data the composite data structure to take values from.
 325:    * @return a new instance containing the values from the 
 326:    *         composite data structure, or <code>null</code>
 327:    *         if the data structure was also <code>null</code>.
 328:    * @throws IllegalArgumentException if the composite data structure
 329:    *                                  does not match the structure
 330:    *                                  outlined above.
 331:    */
 332:   public static ThreadInfo from(CompositeData data)
 333:   {
 334:     if (data == null)
 335:       return null;
 336:     CompositeType type = data.getCompositeType();
 337:     checkAttribute(type, "threadId", SimpleType.LONG);
 338:     checkAttribute(type, "threadName", SimpleType.STRING);
 339:     checkAttribute(type, "threadState", SimpleType.STRING);
 340:     checkAttribute(type, "suspended", SimpleType.BOOLEAN);
 341:     checkAttribute(type, "inNative", SimpleType.BOOLEAN);
 342:     checkAttribute(type, "blockedCount", SimpleType.LONG);
 343:     checkAttribute(type, "blockedTime", SimpleType.LONG);
 344:     checkAttribute(type, "waitedCount", SimpleType.LONG);
 345:     checkAttribute(type, "waitedTime", SimpleType.LONG);
 346:     checkAttribute(type, "lockName", SimpleType.STRING);
 347:     checkAttribute(type, "lockOwnerId", SimpleType.LONG);
 348:     checkAttribute(type, "lockOwnerName", SimpleType.STRING);
 349:     try
 350:       {
 351:     CompositeType seType = 
 352:       new CompositeType(StackTraceElement.class.getName(),
 353:                 "An element of a stack trace",
 354:                 new String[] { "className", "methodName",
 355:                        "fileName", "lineNumber",
 356:                        "nativeMethod" 
 357:                 },
 358:                 new String[] { "Name of the class",
 359:                        "Name of the method",
 360:                        "Name of the source code file",
 361:                        "Line number",
 362:                        "True if this is a native method" 
 363:                 },
 364:                 new OpenType[] {
 365:                   SimpleType.STRING, SimpleType.STRING,
 366:                   SimpleType.STRING, SimpleType.INTEGER,
 367:                   SimpleType.BOOLEAN 
 368:                 });
 369:     checkAttribute(type, "stackTrace", new ArrayType(1, seType));
 370:       }
 371:     catch (OpenDataException e)
 372:       {
 373:     throw new IllegalStateException("Something went wrong in creating " +
 374:                     "the composite data type for the " +
 375:                     "stack trace element.", e);
 376:       }
 377:     CompositeData[] dTraces = (CompositeData[]) data.get("stackTrace");
 378:     StackTraceElement[] traces = new StackTraceElement[dTraces.length];
 379:     for (int a = 0; a < dTraces.length; ++a)
 380:     /* FIXME: We can't use the boolean as there is no available
 381:        constructor. */
 382:       traces[a] = 
 383:     new StackTraceElement((String) dTraces[a].get("className"),
 384:                   (String) dTraces[a].get("methodName"),
 385:                   (String) dTraces[a].get("fileName"),
 386:                   ((Integer) 
 387:                    dTraces[a].get("lineNumber")).intValue());
 388:     return new ThreadInfo(((Long) data.get("threadId")).longValue(),
 389:               (String) data.get("threadName"),
 390:               (String) data.get("threadState"),
 391:               ((Long) data.get("blockedCount")).longValue(),
 392:               ((Long) data.get("blockedTime")).longValue(),
 393:               (String) data.get("lockName"),
 394:               ((Long) data.get("lockOwnerId")).longValue(),
 395:               (String) data.get("lockOwnerName"),  
 396:               ((Long) data.get("waitedCount")).longValue(),
 397:               ((Long) data.get("waitedTime")).longValue(),
 398:               ((Boolean) data.get("inNative")).booleanValue(),
 399:               ((Boolean) data.get("suspended")).booleanValue(),
 400:               traces);
 401:   }
 402: 
 403:   /**
 404:    * Returns the number of times this thread has been
 405:    * in the {@link java.lang.Thread.State#BLOCKED} state.
 406:    * A thread enters this state when it is waiting to
 407:    * obtain an object's monitor.  This may occur either
 408:    * on entering a synchronized method for the first time,
 409:    * or on re-entering it following a call to
 410:    * {@link java.lang.Object#wait()}.
 411:    *
 412:    * @return the number of times this thread has been blocked.
 413:    */
 414:   public long getBlockedCount()
 415:   {
 416:     return blockedCount;
 417:   }
 418: 
 419:   /**
 420:    * <p>
 421:    * Returns the accumulated number of milliseconds this
 422:    * thread has been in the
 423:    * {@link java.lang.Thread.State#BLOCKED} state
 424:    * since thread contention monitoring was last enabled.
 425:    * A thread enters this state when it is waiting to
 426:    * obtain an object's monitor.  This may occur either
 427:    * on entering a synchronized method for the first time,
 428:    * or on re-entering it following a call to
 429:    * {@link java.lang.Object#wait()}.
 430:    * </p>
 431:    * <p>
 432:    * Use of this method requires virtual machine support
 433:    * for thread contention monitoring and for this support
 434:    * to be enabled.
 435:    * </p>
 436:    * 
 437:    * @return the accumulated time (in milliseconds) that this
 438:    *         thread has spent in the blocked state, since
 439:    *         thread contention monitoring was enabled, or -1
 440:    *         if thread contention monitoring is disabled.
 441:    * @throws UnsupportedOperationException if the virtual
 442:    *                                       machine does not
 443:    *                                       support contention
 444:    *                                       monitoring.
 445:    * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
 446:    * @see ThreadMXBean#isThreadContentionMonitoringSupported()
 447:    */
 448:   public long getBlockedTime()
 449:   {
 450:     if (bean == null)
 451:       bean = ManagementFactory.getThreadMXBean();
 452:     // Will throw UnsupportedOperationException for us
 453:     if (bean.isThreadContentionMonitoringEnabled())
 454:       return blockedTime;
 455:     else
 456:       return -1;
 457:   }
 458: 
 459:   /**
 460:    * <p>
 461:    * Returns a {@link java.lang.String} representation of
 462:    * the monitor lock on which this thread is blocked.  If
 463:    * the thread is not blocked, this method returns
 464:    * <code>null</code>.
 465:    * </p>
 466:    * <p>
 467:    * The returned {@link java.lang.String} is constructed
 468:    * using the class name and identity hashcode (usually
 469:    * the memory address of the object) of the lock.  The
 470:    * two are separated by the '@' character, and the identity
 471:    * hashcode is represented in hexadecimal.  Thus, for a
 472:    * lock, <code>l</code>, the returned value is
 473:    * the result of concatenating
 474:    * <code>l.getClass().getName()</code>, <code>"@"</code>
 475:    * and
 476:    * <code>Integer.toHexString(System.identityHashCode(l))</code>.
 477:    * The value is only unique to the extent that the identity
 478:    * hash code is also unique.
 479:    * </p>
 480:    *
 481:    * @return a string representing the lock on which this
 482:    *         thread is blocked, or <code>null</code> if
 483:    *         the thread is not blocked.
 484:    */
 485:   public String getLockName()
 486:   {
 487:     if (threadState.equals("BLOCKED"))
 488:       return null;
 489:     return lockName;
 490:   }
 491: 
 492:   /**
 493:    * Returns the identifier of the thread which owns the
 494:    * monitor lock this thread is waiting for.  -1 is returned
 495:    * if either this thread is not blocked, or the lock is
 496:    * not held by any other thread.
 497:    * 
 498:    * @return the thread identifier of thread holding the lock
 499:    *         this thread is waiting for, or -1 if the thread
 500:    *         is not blocked or the lock is not held by another
 501:    *         thread.
 502:    */
 503:   public long getLockOwnerId()
 504:   {
 505:     if (threadState.equals("BLOCKED"))
 506:       return -1;
 507:     return lockOwnerId;
 508:   }
 509: 
 510:   /**
 511:    * Returns the name of the thread which owns the
 512:    * monitor lock this thread is waiting for.  <code>null</code>
 513:    * is returned if either this thread is not blocked,
 514:    * or the lock is not held by any other thread.
 515:    * 
 516:    * @return the thread identifier of thread holding the lock
 517:    *         this thread is waiting for, or <code>null</code>
 518:    *         if the thread is not blocked or the lock is not
 519:    *         held by another thread.
 520:    */
 521:   public String getLockOwnerName()
 522:   {
 523:     if (threadState.equals("BLOCKED"))
 524:       return null;
 525:     return lockOwnerName;
 526:   }
 527: 
 528:   /**
 529:    * <p>
 530:    * Returns the stack trace of this thread to the depth
 531:    * specified on creation of this {@link ThreadInfo}
 532:    * object.  If the depth is zero, an empty array will
 533:    * be returned.  For non-zero arrays, the elements
 534:    * start with the most recent trace at position zero.
 535:    * The bottom of the stack represents the oldest method
 536:    * invocation which meets the depth requirements.
 537:    * </p>
 538:    * <p>
 539:    * Some virtual machines may not be able to return
 540:    * stack trace information for a thread.  In these
 541:    * cases, an empty array will also be returned.
 542:    * </p>
 543:    * 
 544:    * @return an array of {@link java.lang.StackTraceElement}s
 545:    *         representing the trace of this thread.
 546:    */
 547:   public StackTraceElement[] getStackTrace()
 548:   {
 549:     return trace;
 550:   }
 551: 
 552:   /**
 553:    * Returns the identifier of the thread associated with
 554:    * this instance of {@link ThreadInfo}.
 555:    *
 556:    * @return the thread's identifier.
 557:    */
 558:   public long getThreadId()
 559:   {
 560:     return threadId;
 561:   }
 562: 
 563:   /**
 564:    * Returns the name of the thread associated with
 565:    * this instance of {@link ThreadInfo}.
 566:    *
 567:    * @return the thread's name.
 568:    */
 569:   public String getThreadName()
 570:   {
 571:     return threadName;
 572:   }
 573: 
 574:   /**
 575:    * Returns the state of the thread associated with
 576:    * this instance of {@link ThreadInfo}.
 577:    *
 578:    * @return the thread's state.
 579:    */
 580:   public String getThreadState()
 581:   {
 582:     return threadState;
 583:   }
 584:     
 585:   /**
 586:    * Returns the number of times this thread has been
 587:    * in the {@link java.lang.Thread.State#WAITING} 
 588:    * or {@link java.lang.Thread.State#TIMED_WAITING} state.
 589:    * A thread enters one of these states when it is waiting
 590:    * due to a call to {@link java.lang.Object.wait()},
 591:    * {@link java.lang.Object.join()} or
 592:    * {@link java.lang.concurrent.locks.LockSupport.park()},
 593:    * either with an infinite or timed delay, respectively. 
 594:    *
 595:    * @return the number of times this thread has been waiting.
 596:    */
 597:   public long getWaitedCount()
 598:   {
 599:     return waitedCount;
 600:   }
 601: 
 602:   /**
 603:    * <p>
 604:    * Returns the accumulated number of milliseconds this
 605:    * thread has been in the
 606:    * {@link java.lang.Thread.State#WAITING} or
 607:    * {@link java.lang.Thread.State#TIMED_WAITING} state,
 608:    * since thread contention monitoring was last enabled.
 609:    * A thread enters one of these states when it is waiting
 610:    * due to a call to {@link java.lang.Object.wait()},
 611:    * {@link java.lang.Object.join()} or
 612:    * {@link java.lang.concurrent.locks.LockSupport.park()},
 613:    * either with an infinite or timed delay, respectively. 
 614:    * </p>
 615:    * <p>
 616:    * Use of this method requires virtual machine support
 617:    * for thread contention monitoring and for this support
 618:    * to be enabled.
 619:    * </p>
 620:    * 
 621:    * @return the accumulated time (in milliseconds) that this
 622:    *         thread has spent in one of the waiting states, since
 623:    *         thread contention monitoring was enabled, or -1
 624:    *         if thread contention monitoring is disabled.
 625:    * @throws UnsupportedOperationException if the virtual
 626:    *                                       machine does not
 627:    *                                       support contention
 628:    *                                       monitoring.
 629:    * @see ThreadMXBean#isThreadContentionMonitoringEnabled()
 630:    * @see ThreadMXBean#isThreadContentionMonitoringSupported()
 631:    */
 632:   public long getWaitedTime()
 633:   {
 634:     if (bean == null)
 635:       bean = ManagementFactory.getThreadMXBean();
 636:     // Will throw UnsupportedOperationException for us
 637:     if (bean.isThreadContentionMonitoringEnabled())
 638:       return waitedTime;
 639:     else
 640:       return -1;
 641:   }
 642: 
 643:   /**
 644:    * Returns true if the thread is in a native method.  This
 645:    * excludes native code which forms part of the virtual
 646:    * machine itself, or which results from Just-In-Time
 647:    * compilation.
 648:    *
 649:    * @return true if the thread is in a native method, false
 650:    *         otherwise.
 651:    */
 652:   public boolean isInNative()
 653:   {
 654:     return isInNative;
 655:   }
 656: 
 657:   /**
 658:    * Returns true if the thread has been suspended using
 659:    * {@link java.lang.Thread#suspend()}.
 660:    *
 661:    * @return true if the thread is suspended, false otherwise.
 662:    */
 663:   public boolean isSuspended()
 664:   {
 665:     return isSuspended;
 666:   }
 667: 
 668:   /**
 669:    * Returns a {@link java.lang.String} representation of
 670:    * this {@link ThreadInfo} object.  This takes the form
 671:    * <code>java.lang.management.ThreadInfo[id=tid, name=n,
 672:    * state=s, blockedCount=bc, waitedCount=wc, isInNative=iin,
 673:    * isSuspended=is]</code>, where <code>tid</code> is
 674:    * the thread identifier, <code>n</code> is the
 675:    * thread name, <code>s</code> is the thread state,
 676:    * <code>bc</code> is the blocked state count,
 677:    * <code>wc</code> is the waiting state count and
 678:    * <code>iin</code> and <code>is</code> are boolean
 679:    * flags to indicate the thread is in native code or
 680:    * suspended respectively.  If the thread is blocked,
 681:    * <code>lock=l, lockOwner=lo</code> is also included,
 682:    * where <code>l</code> is the lock waited for, and
 683:    * <code>lo</code> is the thread which owns the lock
 684:    * (or null if there is no owner).
 685:    *
 686:    * @return the string specified above.
 687:    */
 688:   public String toString()
 689:   {
 690:     return getClass().getName() +
 691:       "[id=" + threadId + 
 692:       ", name=" + threadName +
 693:       ", state=" + threadState +
 694:       ", blockedCount=" + blockedCount +
 695:       ", waitedCount=" + waitedCount +
 696:       ", isInNative=" + isInNative + 
 697:       ", isSuspended=" + isSuspended +
 698:       (threadState.equals("BLOCKED") ? 
 699:        ", lockOwnerId=" + lockOwnerId +
 700:        ", lockOwnerName=" + lockOwnerName : "") +
 701:       "]";
 702:   }
 703: 
 704: }