1. /*
  2. * @(#)ThreadInfo.java 1.16 04/04/18
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang.management;
  8. import javax.management.openmbean.CompositeData;
  9. import sun.management.ThreadInfoCompositeData;
  10. /**
  11. * Thread information. <tt>ThreadInfo</tt> contains the information
  12. * about a thread including:
  13. * <h4>General thread information</h4>
  14. * <ul>
  15. * <li>Thread ID.</li>
  16. * <li>Name of the thread.</li>
  17. * </ul>
  18. *
  19. * <h4>Execution information</h4>
  20. * <ul>
  21. * <li>Thread state.</tt>
  22. * <li>The object upon which the thread is blocked waiting to enter
  23. * a synchronization block or waiting to be notified in
  24. * a {@link Object#wait Object.wait} call.</li>
  25. * <li>The ID of the thread that owns the object
  26. * that the thread is blocked.</li>
  27. * <li>Stack trace of the thread.</li>
  28. * </ul>
  29. *
  30. * <h4>Synchronization statistics</h4>
  31. * <ul>
  32. * <li>The number of times that the thread has blocked for
  33. * synchronization or waited for notification.</li>
  34. * <li>The accumulated elapsed time that the thread has blocked
  35. * for synchronization or waited for notification
  36. * since thread contention monitoring
  37. * was enabled. Some Java virtual machine implementation
  38. * may not support this. The
  39. * {@link ThreadMXBean#isThreadContentionMonitoringSupported()}
  40. * method can be used to determine if a Java virtual machine
  41. * supports this.</li>
  42. * </ul>
  43. *
  44. * <p>This thread information class is designed for use in monitoring of
  45. * the system, not for synchronization control.
  46. *
  47. * <h4>MXBean Mapping</h4>
  48. * <tt>ThreadInfo</tt> is mapped to a {@link CompositeData CompositeData}
  49. * with attributes as specified in
  50. * the {@link #from from} method.
  51. *
  52. * @see ThreadMXBean#isThreadContentionMonitoringSupported
  53. *
  54. * @author Mandy Chung
  55. * @version 1.16, 04/18/04
  56. * @since 1.5
  57. */
  58. public class ThreadInfo {
  59. private final String threadName;
  60. private final long threadId;
  61. private final long blockedTime;
  62. private final long blockedCount;
  63. private final long waitedTime;
  64. private final long waitedCount;
  65. private final String lockName;
  66. private final long lockOwnerId;
  67. private final String lockOwnerName;
  68. private final boolean inNative;
  69. private final boolean suspended;
  70. private final Thread.State threadState;
  71. private final StackTraceElement[] stackTrace;
  72. /**
  73. * Constructor of ThreadInfo created by the JVM
  74. *
  75. * @param t Thread
  76. * @param state Thread state
  77. * @param lockObj Object on which the thread is blocked
  78. * to enter or waiting
  79. * @param lockOwner the thread holding the lock
  80. * @param blockedCount Number of times blocked to enter a lock
  81. * @param blockedTime Approx time blocked to enter a lock
  82. * @param waitedCount Number of times waited on a lock
  83. * @param waitedTime Approx time waited on a lock
  84. * @param stackTrace Thread stack trace
  85. */
  86. private ThreadInfo(Thread t, int state, Object lockObj, Thread lockOwner,
  87. long blockedCount, long blockedTime,
  88. long waitedCount, long waitedTime,
  89. StackTraceElement[] stackTrace) {
  90. this.threadId = t.getId();
  91. this.threadName = t.getName();
  92. this.threadState =
  93. sun.management.ManagementFactory.toThreadState(state);
  94. this.suspended =
  95. sun.management.ManagementFactory.isThreadSuspended(state);
  96. this.inNative =
  97. sun.management.ManagementFactory.isThreadRunningNative(state);
  98. this.blockedCount = blockedCount;
  99. this.blockedTime = blockedTime;
  100. this.waitedCount = waitedCount;
  101. this.waitedTime = waitedTime;
  102. if (lockObj == null) {
  103. this.lockName = null;
  104. } else {
  105. this.lockName =
  106. lockObj.getClass().getName() + '@' +
  107. Integer.toHexString(System.identityHashCode(lockObj));
  108. }
  109. if (lockOwner == null) {
  110. this.lockOwnerId = -1;
  111. this.lockOwnerName = null;
  112. } else {;
  113. this.lockOwnerId = lockOwner.getId();
  114. this.lockOwnerName = lockOwner.getName();
  115. }
  116. this.stackTrace = stackTrace;
  117. }
  118. /*
  119. * Constructs a <tt>ThreadInfo</tt> object from a
  120. * {@link CompositeData CompositeData}.
  121. */
  122. private ThreadInfo(CompositeData cd) {
  123. ThreadInfoCompositeData.validateCompositeData(cd);
  124. threadId = ThreadInfoCompositeData.getThreadId(cd);
  125. threadName = ThreadInfoCompositeData.getThreadName(cd);
  126. blockedTime = ThreadInfoCompositeData.getBlockedTime(cd);
  127. blockedCount = ThreadInfoCompositeData.getBlockedCount(cd);
  128. waitedTime = ThreadInfoCompositeData.getWaitedTime(cd);
  129. waitedCount = ThreadInfoCompositeData.getWaitedCount(cd);
  130. lockName = ThreadInfoCompositeData.getLockName(cd);
  131. lockOwnerId = ThreadInfoCompositeData.getLockOwnerId(cd);
  132. lockOwnerName = ThreadInfoCompositeData.getLockOwnerName(cd);
  133. threadState = ThreadInfoCompositeData.getThreadState(cd);
  134. suspended = ThreadInfoCompositeData.isSuspended(cd);
  135. inNative = ThreadInfoCompositeData.isInNative(cd);
  136. stackTrace = ThreadInfoCompositeData.getStackTrace(cd);
  137. }
  138. /**
  139. * Returns the ID of the thread associated with this <tt>ThreadInfo</tt>.
  140. *
  141. * @return the ID of the associated thread.
  142. */
  143. public long getThreadId() {
  144. return threadId;
  145. }
  146. /**
  147. * Returns the name of the thread associated with this <tt>ThreadInfo</tt>.
  148. *
  149. * @return the name of the associated thread.
  150. */
  151. public String getThreadName() {
  152. return threadName;
  153. }
  154. /**
  155. * Returns the state of the thread associated with this <tt>ThreadInfo</tt>.
  156. *
  157. * @return <tt>Thread.State</tt> of the associated thread.
  158. */
  159. public Thread.State getThreadState() {
  160. return threadState;
  161. }
  162. /**
  163. * Returns the approximate accumulated elapsed time (in milliseconds)
  164. * that the thread associated with this <tt>ThreadInfo</tt>
  165. * has blocked to enter or reenter a monitor
  166. * since thread contention monitoring is enabled.
  167. * I.e. the total accumulated time the thread has been in the
  168. * {@link java.lang.Thread.State#BLOCKED BLOCKED} state since thread
  169. * contention monitoring was last enabled.
  170. * This method returns <tt>-1</tt> if thread contention monitoring
  171. * is disabled.
  172. *
  173. * <p>The Java virtual machine may measure the time with a high
  174. * resolution timer. This statistic is reset when
  175. * the thread contention monitoring is reenabled.
  176. *
  177. * @return the approximate accumulated elapsed time in milliseconds
  178. * that a thread entered the <tt>BLOCKED</tt> state;
  179. * <tt>-1</tt> if thread contention monitoring is disabled.
  180. *
  181. * @throws java.lang.UnsupportedOperationException if the Java
  182. * virtual machine does not support this operation.
  183. *
  184. * @see ThreadMXBean#isThreadContentionMonitoringSupported
  185. * @see ThreadMXBean#setThreadContentionMonitoringEnabled
  186. */
  187. public long getBlockedTime() {
  188. return blockedTime;
  189. }
  190. /**
  191. * Returns the total number of times that
  192. * the thread associated with this <tt>ThreadInfo</tt>
  193. * blocked to enter or reenter a monitor.
  194. * I.e. the number of times a thread has been in the
  195. * {@link java.lang.Thread.State#BLOCKED BLOCKED} state.
  196. *
  197. * @return the total number of times that the thread
  198. * entered the <tt>BLOCKED</tt> state.
  199. */
  200. public long getBlockedCount() {
  201. return blockedCount;
  202. }
  203. /**
  204. * Returns the approximate accumulated elapsed time (in milliseconds)
  205. * that the thread associated with this <tt>ThreadInfo</tt>
  206. * has waited for notification
  207. * since thread contention monitoring is enabled.
  208. * I.e. the total accumulated time the thread has been in the
  209. * {@link java.lang.Thread.State#WAITING WAITING}
  210. * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state
  211. * since thread contention monitoring is enabled.
  212. * This method returns <tt>-1</tt> if thread contention monitoring
  213. * is disabled.
  214. *
  215. * <p>The Java virtual machine may measure the time with a high
  216. * resolution timer. This statistic is reset when
  217. * the thread contention monitoring is reenabled.
  218. *
  219. * @return the approximate accumulated elapsed time in milliseconds
  220. * that a thread has been in the <tt>WAITING</tt> or
  221. * <tt>TIMED_WAITING</tt> state;
  222. * <tt>-1</tt> if thread contention monitoring is disabled.
  223. *
  224. * @throws java.lang.UnsupportedOperationException if the Java
  225. * virtual machine does not support this operation.
  226. *
  227. * @see ThreadMXBean#isThreadContentionMonitoringSupported
  228. * @see ThreadMXBean#setThreadContentionMonitoringEnabled
  229. */
  230. public long getWaitedTime() {
  231. return waitedTime;
  232. }
  233. /**
  234. * Returns the total number of times that
  235. * the thread associated with this <tt>ThreadInfo</tt>
  236. * waited for notification.
  237. * I.e. the number of times that a thread has been
  238. * in the {@link java.lang.Thread.State#WAITING WAITING}
  239. * or {@link java.lang.Thread.State#TIMED_WAITING TIMED_WAITING} state.
  240. *
  241. * @return the total number of times that the thread
  242. * was in the <tt>WAITING</tt> or <tt>TIMED_WAITING</tt> state.
  243. */
  244. public long getWaitedCount() {
  245. return waitedCount;
  246. }
  247. /**
  248. * Returns the string representation of the monitor lock that
  249. * the thread associated with this <tt>ThreadInfo</tt>
  250. * is blocked to enter or waiting to be notified through
  251. * the {@link Object#wait Object.wait} method.
  252. * The returned string representation of a monitor lock consists of
  253. * the name of the class of which the object is an instance, the
  254. * at-sign character `@', and the unsigned hexadecimal representation
  255. * of the <em>identity</em> hash code of the object.
  256. * The returned string may not
  257. * be unique depending on the implementation of the
  258. * {@link System#identityHashCode} method.
  259. * This method returns a string equals to the value of:
  260. * <blockquote>
  261. * <pre>
  262. * lock.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(lock))
  263. * </pre></blockquote>
  264. * where <tt>lock</tt> is the monitor lock object.
  265. *
  266. * <p>If the thread is not blocking to enter on any monitor object,
  267. * or is not waiting on a monitor object for notification in a
  268. * <tt>Object.wait</tt> call,
  269. * this method returns <tt>null</tt>.
  270. *
  271. * @return the string representation of the monitor lock that
  272. * the thread is blocking to enter or waiting to be notified through
  273. * the <tt>Object.wait</tt> method if any;
  274. * <tt>null</tt> otherwise.
  275. *
  276. */
  277. public String getLockName() {
  278. return lockName;
  279. }
  280. /**
  281. * Returns the ID of the thread which holds the monitor lock of an object
  282. * on which the thread associated with this <tt>ThreadInfo</tt>
  283. * is blocking.
  284. * This method will return <tt>-1</tt> if this thread is not blocked
  285. * or waiting on any monitor, or if the monitor lock is not held
  286. * by any thread.
  287. *
  288. * @return the thread ID of the owner thread of the monitor lock of the
  289. * object this thread is blocking on;
  290. * <tt>-1</tt> if this thread is not blocked
  291. * or waiting on any monitor, or if the monitor lock is not held
  292. * by any thread.
  293. *
  294. * @see #getLockName
  295. */
  296. public long getLockOwnerId() {
  297. return lockOwnerId;
  298. }
  299. /**
  300. * Returns the name of the thread which holds the monitor lock of an object
  301. * on which the thread associated with this <tt>ThreadInfo</tt>
  302. * is blocking.
  303. * This method will return <tt>null</tt> if this thread is not blocked
  304. * or waiting on any monitor, or if the monitor lock is not held
  305. * by any thread.
  306. *
  307. * @return the name of the thread that holds the monitor lock of the object
  308. * this thread is blocking on;
  309. * <tt>null</tt> if this thread is not blocked
  310. * or waiting on any monitor, or if the monitor lock is not held
  311. * by any thread.
  312. *
  313. * @see #getLockName
  314. */
  315. public String getLockOwnerName() {
  316. return lockOwnerName;
  317. }
  318. /**
  319. * Returns the stack trace of the thread
  320. * associated with this <tt>ThreadInfo</tt>.
  321. * If no stack trace was requested for this thread info, this method
  322. * will return a zero-length array.
  323. * If the returned array is of non-zero length then the first element of
  324. * the array represents the top of the stack, which is the most recent
  325. * method invocation in the sequence. The last element of the array
  326. * represents the bottom of the stack, which is the least recent method
  327. * invocation in the sequence.
  328. *
  329. * <p>Some Java virtual machines may, under some circumstances, omit one
  330. * or more stack frames from the stack trace. In the extreme case,
  331. * a virtual machine that has no stack trace information concerning
  332. * the thread associated with this <tt>ThreadInfo</tt>
  333. * is permitted to return a zero-length array from this method.
  334. *
  335. * @return an array of <tt>StackTraceElement</tt> objects of the thread.
  336. */
  337. public StackTraceElement[] getStackTrace() {
  338. if (stackTrace == null) {
  339. return NO_STACK_TRACE;
  340. } else {
  341. return stackTrace;
  342. }
  343. }
  344. /**
  345. * Tests if the thread associated with this <tt>ThreadInfo</tt>
  346. * is suspended. This method returns <tt>true</tt> if
  347. * {@link Thread#suspend} has been called.
  348. *
  349. * @return <tt>true</tt> if the thread is suspended;
  350. * <tt>false</tt> otherwise.
  351. */
  352. public boolean isSuspended() {
  353. return suspended;
  354. }
  355. /**
  356. * Tests if the thread associated with this <tt>ThreadInfo</tt>
  357. * is executing native code via the Java Native Interface (JNI).
  358. * The JNI native code does not include
  359. * the virtual machine support code or the compiled native
  360. * code generated by the virtual machine.
  361. *
  362. * @return <tt>true</tt> if the thread is executing native code;
  363. * <tt>false</tt> otherwise.
  364. */
  365. public boolean isInNative() {
  366. return inNative;
  367. }
  368. /**
  369. * Returns a string representation of this thread info.
  370. *
  371. * @return a string representation of this thread info.
  372. */
  373. public String toString() {
  374. return "Thread " + getThreadName() + " (Id = " + getThreadId() + ") " +
  375. getThreadState() + " " + getLockName();
  376. }
  377. /**
  378. * Returns a <tt>ThreadInfo</tt> object represented by the
  379. * given <tt>CompositeData</tt>.
  380. * The given <tt>CompositeData</tt> must contain the following attributes:
  381. * <blockquote>
  382. * <table border>
  383. * <tr>
  384. * <th align=left>Attribute Name</th>
  385. * <th align=left>Type</th>
  386. * </tr>
  387. * <tr>
  388. * <td>threadId</td>
  389. * <td><tt>java.lang.Long</tt></td>
  390. * </tr>
  391. * <tr>
  392. * <td>threadName</td>
  393. * <td><tt>java.lang.String</tt></td>
  394. * </tr>
  395. * <tr>
  396. * <td>threadState</td>
  397. * <td><tt>java.lang.String</tt></td>
  398. * </tr>
  399. * <tr>
  400. * <td>suspended</td>
  401. * <td><tt>java.lang.Boolean</tt></td>
  402. * </tr>
  403. * <tr>
  404. * <td>inNative</td>
  405. * <td><tt>java.lang.Boolean</tt></td>
  406. * </tr>
  407. * <tr>
  408. * <td>blockedCount</td>
  409. * <td><tt>java.lang.Long</tt></td>
  410. * </tr>
  411. * <tr>
  412. * <td>blockedTime</td>
  413. * <td><tt>java.lang.Long</tt></td>
  414. * </tr>
  415. * <tr>
  416. * <td>waitedCount</td>
  417. * <td><tt>java.lang.Long</tt></td>
  418. * </tr>
  419. * <tr>
  420. * <td>waitedTime</td>
  421. * <td><tt>java.lang.Long</tt></td>
  422. * </tr>
  423. * <tr>
  424. * <td>lockName</td>
  425. * <td><tt>java.lang.String</tt></td>
  426. * </tr>
  427. * <tr>
  428. * <td>lockOwnerId</td>
  429. * <td><tt>java.lang.Long</tt></td>
  430. * </tr>
  431. * <tr>
  432. * <td>lockOwnerName</td>
  433. * <td><tt>java.lang.String</tt></td>
  434. * </tr>
  435. * <tr>
  436. * <td>stackTrace</td>
  437. * <td><tt>javax.management.openmbean.CompositeData[]</tt>
  438. * <p>
  439. * Each element is a <tt>CompositeData</tt> representing
  440. * StackTraceElement containing the following attributes:
  441. * <blockquote>
  442. * <table cellspacing=1 cellpadding=0>
  443. * <tr>
  444. * <th align=left>Attribute Name</th>
  445. * <th align=left>Type</th>
  446. * </tr>
  447. * <tr>
  448. * <td>className</td>
  449. * <td><tt>java.lang.String</tt></td>
  450. * </tr>
  451. * <tr>
  452. * <td>methodName</td>
  453. * <td><tt>java.lang.String</tt></td>
  454. * </tr>
  455. * <tr>
  456. * <td>fileName</td>
  457. * <td><tt>java.lang.String</tt></td>
  458. * </tr>
  459. * <tr>
  460. * <td>lineNumber</td>
  461. * <td><tt>java.lang.Integer</tt></td>
  462. * </tr>
  463. * <tr>
  464. * <td>nativeMethod</td>
  465. * <td><tt>java.lang.Boolean</tt></td>
  466. * </tr>
  467. * </table>
  468. * </blockquote>
  469. * </td>
  470. * </tr>
  471. * </table>
  472. * </blockquote>
  473. *
  474. * @param cd <tt>CompositeData</tt> representing a <tt>ThreadInfo</tt>
  475. *
  476. * @throws IllegalArgumentException if <tt>cd</tt> does not
  477. * represent a <tt>ThreadInfo</tt> with the attributes described
  478. * above.
  479. * @return a <tt>ThreadInfo</tt> object represented
  480. * by <tt>cd</tt> if <tt>cd</tt> is not <tt>null</tt>
  481. * <tt>null</tt> otherwise.
  482. */
  483. public static ThreadInfo from(CompositeData cd) {
  484. if (cd == null) {
  485. return null;
  486. }
  487. if (cd instanceof ThreadInfoCompositeData) {
  488. return ((ThreadInfoCompositeData) cd).getThreadInfo();
  489. } else {
  490. return new ThreadInfo(cd);
  491. }
  492. }
  493. private static final StackTraceElement[] NO_STACK_TRACE =
  494. new StackTraceElement[0];
  495. }