001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.lang.management;
019:
020: import java.lang.management.ManagementPermission;
021: import java.lang.management.ThreadInfo;
022: import java.lang.management.ThreadMXBean;
023: import java.security.AccessController;
024: import java.security.PrivilegedAction;
025:
026: /**
027: * Runtime type for {@link java.lang.management.ThreadMXBean}
028: *
029: * @since 1.5
030: */
031: public final class ThreadMXBeanImpl extends DynamicMXBeanImpl implements
032: ThreadMXBean {
033:
034: private static ThreadMXBeanImpl instance = new ThreadMXBeanImpl();
035:
036: /**
037: * Constructor intentionally private to prevent instantiation by others.
038: * Sets the metadata for this bean.
039: */
040: private ThreadMXBeanImpl() {
041: setMBeanInfo(ManagementUtils.getMBeanInfo(ThreadMXBean.class
042: .getName()));
043: }
044:
045: /**
046: * Singleton accessor method.
047: *
048: * @return the <code>ThreadMXBeanImpl</code> singleton.
049: */
050: static ThreadMXBeanImpl getInstance() {
051: return instance;
052: }
053:
054: /**
055: * @return an array of the identifiers of every thread in the virtual
056: * machine that has been detected as currently being in a deadlock
057: * situation.
058: * @see #findMonitorDeadlockedThreads()
059: */
060: private native long[] findMonitorDeadlockedThreadsImpl();
061:
062: /*
063: * (non-Javadoc)
064: *
065: * @see java.lang.management.ThreadMXBean#findMonitorDeadlockedThreads()
066: */
067: public long[] findMonitorDeadlockedThreads() {
068: SecurityManager security = System.getSecurityManager();
069: if (security != null) {
070: security
071: .checkPermission(new ManagementPermission("monitor"));
072: }
073: return this .findMonitorDeadlockedThreadsImpl();
074: }
075:
076: /**
077: * @return the identifiers of all of the threads currently alive in the
078: * virtual machine.
079: * @see #getAllThreadIds()
080: */
081: private native long[] getAllThreadIdsImpl();
082:
083: /*
084: * (non-Javadoc)
085: *
086: * @see java.lang.management.ThreadMXBean#getAllThreadIds()
087: */
088: public long[] getAllThreadIds() {
089: SecurityManager security = System.getSecurityManager();
090: if (security != null) {
091: security
092: .checkPermission(new ManagementPermission("monitor"));
093: }
094: return this .getAllThreadIdsImpl();
095: }
096:
097: /*
098: * (non-Javadoc)
099: *
100: * @see java.lang.management.ThreadMXBean#getCurrentThreadCpuTime()
101: */
102: public long getCurrentThreadCpuTime() {
103: return getThreadCpuTime(Thread.currentThread().getId());
104: }
105:
106: /*
107: * (non-Javadoc)
108: *
109: * @see java.lang.management.ThreadMXBean#getCurrentThreadUserTime()
110: */
111: public long getCurrentThreadUserTime() {
112: return getThreadUserTime(Thread.currentThread().getId());
113: }
114:
115: /**
116: * @return the number of currently alive daemon threads.
117: * @see #getDaemonThreadCount()
118: */
119: private native int getDaemonThreadCountImpl();
120:
121: /*
122: * (non-Javadoc)
123: *
124: * @see java.lang.management.ThreadMXBean#getDaemonThreadCount()
125: */
126: public int getDaemonThreadCount() {
127: return this .getDaemonThreadCountImpl();
128: }
129:
130: /**
131: * @return the peak number of live threads
132: * @see #getPeakThreadCount()
133: */
134: private native int getPeakThreadCountImpl();
135:
136: /*
137: * (non-Javadoc)
138: *
139: * @see java.lang.management.ThreadMXBean#getPeakThreadCount()
140: */
141: public int getPeakThreadCount() {
142: return this .getPeakThreadCountImpl();
143: }
144:
145: /**
146: * @return the number of currently alive threads.
147: * @see #getThreadCount()
148: */
149: private native int getThreadCountImpl();
150:
151: /*
152: * (non-Javadoc)
153: *
154: * @see java.lang.management.ThreadMXBean#getThreadCount()
155: */
156: public int getThreadCount() {
157: return this .getThreadCountImpl();
158: }
159:
160: /**
161: * @param id
162: * the identifier for a thread. Must be a positive number greater
163: * than zero.
164: * @return on virtual machines where thread CPU timing is supported and
165: * enabled, and there is a living thread with identifier
166: * <code>id</code>, the number of nanoseconds CPU time used by
167: * the thread. On virtual machines where thread CPU timing is
168: * supported but not enabled, or where there is no living thread
169: * with identifier <code>id</code> present in the virtual machine,
170: * a value of <code>-1</code> is returned.
171: * @see #getThreadCpuTime(long)
172: */
173: private native long getThreadCpuTimeImpl(long id);
174:
175: /*
176: * (non-Javadoc)
177: *
178: * @see java.lang.management.ThreadMXBean#getThreadCpuTime(long)
179: */
180: public long getThreadCpuTime(long id) {
181: // Validate input.
182: if (id <= 0) {
183: throw new IllegalArgumentException(
184: "Thread id must be greater than 0.");
185: }
186:
187: long result = -1;
188: if (isThreadCpuTimeSupported()) {
189: if (isThreadCpuTimeEnabled()) {
190: result = this .getThreadCpuTimeImpl(id);
191: }
192: } else {
193: throw new UnsupportedOperationException(
194: "CPU time measurement is not supported on this virtual machine.");
195: }
196: return result;
197: }
198:
199: /*
200: * (non-Javadoc)
201: *
202: * @see java.lang.management.ThreadMXBean#getThreadInfo(long)
203: */
204: public ThreadInfo getThreadInfo(long id) {
205: return getThreadInfo(id, 0);
206: }
207:
208: /*
209: * (non-Javadoc)
210: *
211: * @see java.lang.management.ThreadMXBean#getThreadInfo(long[])
212: */
213: public ThreadInfo[] getThreadInfo(long[] ids) {
214: return getThreadInfo(ids, 0);
215: }
216:
217: /*
218: * (non-Javadoc)
219: *
220: * @see java.lang.management.ThreadMXBean#getThreadInfo(long[], int)
221: */
222: public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
223: SecurityManager security = System.getSecurityManager();
224: if (security != null) {
225: security
226: .checkPermission(new ManagementPermission("monitor"));
227: }
228:
229: // Validate inputs
230: for (int i = 0; i < ids.length; i++) {
231: if (ids[i] <= 0) {
232: throw new IllegalArgumentException(
233: "Thread id must be greater than 0.");
234: }
235: }
236:
237: if (maxDepth < 0) {
238: throw new IllegalArgumentException(
239: "maxDepth value cannot be negative.");
240: }
241:
242: // Create an array and populate with individual ThreadInfos
243: ThreadInfo[] tis = new ThreadInfo[ids.length];
244: for (int i = 0; i < ids.length; i++) {
245: tis[i] = this .getThreadInfoImpl(ids[i], maxDepth);
246: }
247: return tis;
248: }
249:
250: /*
251: * (non-Javadoc)
252: *
253: * @see java.lang.management.ThreadMXBean#getThreadInfo(long, int)
254: */
255: public ThreadInfo getThreadInfo(long id, int maxDepth) {
256: SecurityManager security = System.getSecurityManager();
257: if (security != null) {
258: security
259: .checkPermission(new ManagementPermission("monitor"));
260: }
261:
262: // Validate inputs
263: if (id <= 0) {
264: throw new IllegalArgumentException(
265: "Thread id must be greater than 0.");
266: }
267: if (maxDepth < 0) {
268: throw new IllegalArgumentException(
269: "maxDepth value cannot be negative.");
270: }
271: return this .getThreadInfoImpl(id, maxDepth);
272: }
273:
274: /**
275: * Returns the corresponding Thread instance for a given thread id
276: *
277: * @param id
278: * id of the thread (must be > 0)
279: * @return null if thread with the id specified does not exist
280: */
281: private native Thread getThreadByIdImpl(long id);
282:
283: /**
284: * Returns the object the thread is either blocked or waiting on
285: *
286: * @param thread
287: * thread
288: * @return null if thread not blocked on an object
289: */
290: private native Object getObjectThreadIsBlockedOnImpl(Thread thread);
291:
292: /**
293: * Returns the thread owning an object
294: *
295: * @param obj
296: * object
297: * @return null if object not owned, else Thread owner
298: */
299: private native Thread getThreadOwningObjectImpl(Object obj);
300:
301: /**
302: * Returns whether the thread is suspended or not
303: *
304: * @param thread
305: * thread
306: * @return true if Thread.suspend() has been called on the thread, otherwise
307: * false
308: */
309: private native boolean isSuspendedImpl(Thread thread);
310:
311: /**
312: * Returns the number of times the thread has waited
313: *
314: * @param thread
315: * thread
316: * @return number of times the thread has waited
317: *
318: */
319: private native long getThreadWaitedCountImpl(Thread thread);
320:
321: /**
322: * Returns the amount of time the thread has waited (in milliseconds)
323: *
324: * @param thread
325: * thread
326: * @return time (in milliseconds) the thread has waited, or -1 if this
327: * feature is not supported
328: *
329: */
330: private native long getThreadWaitedTimeImpl(Thread thread);
331:
332: /**
333: * Returns the amount of time the thread has blocked (in milliseconds)
334: *
335: * @param thread
336: * thread
337: * @return time (in milliseconds) the thread has blocked, or -1 if this
338: * feature is not supported
339: *
340: */
341: private native long getThreadBlockedTimeImpl(Thread thread);
342:
343: /**
344: * Returns the number of times the thread has blocked on a monitor
345: *
346: * @param thread
347: * thread
348: * @return number of times the thread has blocked
349: *
350: */
351: private native long getThreadBlockedCountImpl(Thread thread);
352:
353: /**
354: * Create an instance of the ThreadInfo class
355: *
356: * @param threadId
357: * @param threadName
358: * @param threadState
359: * @param suspended
360: * @param inNative
361: * @param blockedCount
362: * @param blockedTime
363: * @param waitedCount
364: * @param waitedTime
365: * @param lockName
366: * @param lockOwnerId
367: * @param lockOwnerName
368: * @param stackTrace
369: * @return
370: */
371: private native ThreadInfo createThreadInfoImpl(long threadId,
372: String threadName, Thread.State threadState,
373: boolean suspended, boolean inNative, long blockedCount,
374: long blockedTime, long waitedCount, long waitedTime,
375: String lockName, long lockOwnerId, String lockOwnerName,
376: StackTraceElement[] stackTrace);
377:
378: /*
379: * Get together information for a thread and create an instance of the
380: * ThreadInfo class
381: *
382: * @param id thread id @param maxDepth maximum depth of the stack trace
383: * @return an instance of ThreadInfo for valid thread ids, otherwise null
384: *
385: */
386: private ThreadInfo getThreadInfoImpl(long id, int maxDepth) {
387: final Thread thread = getThreadByIdImpl(id);
388: if (null == thread) {
389: return null;
390: }
391:
392: // Generic thread info
393: long threadId = thread.getId();
394: String threadName = thread.getName();
395: Thread.State threadState = thread.getState();
396:
397: // Waited and blocked information
398: long waitedTime = -1;
399: long blockedTime = -1;
400: // Waited and blocked times to be -1 if ThreadContentionMonitoring
401: // is not supported
402: if (isThreadContentionMonitoringSupported()
403: && isThreadContentionMonitoringEnabled()) {
404: waitedTime = getThreadWaitedTimeImpl(thread);
405: blockedTime = getThreadBlockedTimeImpl(thread);
406: }
407:
408: // Get together information about any locks involved
409: // i.e. thread blocked or waiting on a lock
410: // see ThreadInfo spec for values if neither blocked nor waiting
411: String lockName = null;
412: long lockOwnerId = -1;
413: String lockOwnerName = null;
414:
415: Object lock = getObjectThreadIsBlockedOnImpl(thread);
416: if (lock != null) {
417: // the format of the name is dictated by the ThreadInfo spec
418: lockName = lock.getClass().getName()
419: + '@'
420: + Integer
421: .toHexString(System.identityHashCode(lock));
422: Thread threadOwningLock = getThreadOwningObjectImpl(lock);
423: // Possible race conditions must be catered for
424: if (threadOwningLock != null) {
425: lockOwnerId = threadOwningLock.getId();
426: lockOwnerName = threadOwningLock.getName();
427: }// end if non-null thread owning lock
428: }// end if non-null lock
429:
430: // Get the stack trace together.
431: // Do we have to prune it for max depth?
432: StackTraceElement[] stackTrace = AccessController
433: .doPrivileged(new PrivilegedAction<StackTraceElement[]>() {
434: public StackTraceElement[] run() {
435: return thread.getStackTrace();
436: }// end method run
437: });
438:
439: boolean isInNative = false;
440: if (stackTrace.length > 0) {
441: isInNative = stackTrace[0].isNativeMethod();
442: }
443: if ((maxDepth < Integer.MAX_VALUE)
444: && (stackTrace.length > maxDepth)) {
445: StackTraceElement[] newStackTrace = new StackTraceElement[maxDepth];
446: for (int i = 0; i < newStackTrace.length; i++) {
447: newStackTrace[i] = stackTrace[i];
448: }
449: stackTrace = newStackTrace;
450: }
451:
452: // Ask our native to instantiate a ThreadInfo for us
453: ThreadInfo ti = createThreadInfoImpl(threadId, threadName,
454: threadState, isSuspendedImpl(thread), isInNative,
455: getThreadBlockedCountImpl(thread), blockedTime,
456: getThreadWaitedCountImpl(thread), waitedTime, lockName,
457: lockOwnerId, lockOwnerName, stackTrace);
458: return ti;
459: }
460:
461: /**
462: * @param id
463: * the identifier for a thread. Must be a positive number greater
464: * than zero.
465: * @return on virtual machines where thread CPU timing is supported and
466: * enabled, and there is a living thread with identifier
467: * <code>id</code>, the number of nanoseconds CPU time used by
468: * the thread running in user mode. On virtual machines where thread
469: * CPU timing is supported but not enabled, or where there is no
470: * living thread with identifier <code>id</code> present in the
471: * virtual machine, a value of <code>-1</code> is returned.
472: * <p>
473: * If thread CPU timing was disabled when the thread was started
474: * then the virtual machine is free to choose any measurement start
475: * time between when the virtual machine started up and when thread
476: * CPU timing was enabled with a call to
477: * {@link #setThreadCpuTimeEnabled(boolean)}.
478: * </p>
479: * @see #getThreadUserTime(long)
480: */
481: private native long getThreadUserTimeImpl(long id);
482:
483: /*
484: * (non-Javadoc)
485: *
486: * @see java.lang.management.ThreadMXBean#getThreadUserTime(long)
487: */
488: public long getThreadUserTime(long id) {
489: // Validate input.
490: if (id <= 0) {
491: throw new IllegalArgumentException(
492: "Thread id must be greater than 0.");
493: }
494:
495: long result = -1;
496: if (isThreadCpuTimeSupported()) {
497: if (isThreadCpuTimeEnabled()) {
498: result = this .getThreadUserTimeImpl(id);
499: }
500: } else {
501: throw new UnsupportedOperationException(
502: "CPU time measurement is not supported on this virtual machine.");
503: }
504: return result;
505: }
506:
507: /**
508: * @return the total number of started threads.
509: * @see #getTotalStartedThreadCount()
510: */
511: private native long getTotalStartedThreadCountImpl();
512:
513: /*
514: * (non-Javadoc)
515: *
516: * @see java.lang.management.ThreadMXBean#getTotalStartedThreadCount()
517: */
518: public long getTotalStartedThreadCount() {
519: return this .getTotalStartedThreadCountImpl();
520: }
521:
522: /**
523: * @return <code>true</code> if CPU timing of the current thread is
524: * supported, otherwise <code>false</code>.
525: * @see #isCurrentThreadCpuTimeSupported()
526: */
527: private native boolean isCurrentThreadCpuTimeSupportedImpl();
528:
529: /*
530: * (non-Javadoc)
531: *
532: * @see java.lang.management.ThreadMXBean#isCurrentThreadCpuTimeSupported()
533: */
534: public boolean isCurrentThreadCpuTimeSupported() {
535: return this .isCurrentThreadCpuTimeSupportedImpl();
536: }
537:
538: /**
539: * @return <code>true</code> if thread contention monitoring is enabled,
540: * <code>false</code> otherwise.
541: * @see #isThreadContentionMonitoringEnabled()
542: */
543: private native boolean isThreadContentionMonitoringEnabledImpl();
544:
545: /*
546: * (non-Javadoc)
547: *
548: * @see java.lang.management.ThreadMXBean#isThreadContentionMonitoringEnabled()
549: */
550: public boolean isThreadContentionMonitoringEnabled() {
551: if (!isThreadContentionMonitoringSupported()) {
552: throw new UnsupportedOperationException(
553: "Thread contention monitoring is not supported on this virtual machine.");
554: }
555: return this .isThreadContentionMonitoringEnabledImpl();
556: }
557:
558: /**
559: * @return <code>true</code> if thread contention monitoring is supported,
560: * <code>false</code> otherwise.
561: * @see #isThreadContentionMonitoringSupported()
562: */
563: private native boolean isThreadContentionMonitoringSupportedImpl();
564:
565: /*
566: * (non-Javadoc)
567: *
568: * @see java.lang.management.ThreadMXBean#isThreadContentionMonitoringSupported()
569: */
570: public boolean isThreadContentionMonitoringSupported() {
571: return this .isThreadContentionMonitoringSupportedImpl();
572: }
573:
574: /**
575: * @return <code>true</code> if thread CPU timing is enabled,
576: * <code>false</code> otherwise.
577: * @see #isThreadCpuTimeEnabled()
578: */
579: private native boolean isThreadCpuTimeEnabledImpl();
580:
581: /*
582: * (non-Javadoc)
583: *
584: * @see java.lang.management.ThreadMXBean#isThreadCpuTimeEnabled()
585: */
586: public boolean isThreadCpuTimeEnabled() {
587: if (!isThreadCpuTimeSupported()) {
588: throw new UnsupportedOperationException(
589: "Thread CPU timing is not supported on this virtual machine.");
590: }
591: return this .isThreadCpuTimeEnabledImpl();
592: }
593:
594: /**
595: * @return <code>true</code> if the virtual machine supports the CPU
596: * timing of threads, <code>false</code> otherwise.
597: * @see #isThreadCpuTimeSupported()
598: */
599: private native boolean isThreadCpuTimeSupportedImpl();
600:
601: /*
602: * (non-Javadoc)
603: *
604: * @see java.lang.management.ThreadMXBean#isThreadCpuTimeSupported()
605: */
606: public boolean isThreadCpuTimeSupported() {
607: return this .isThreadCpuTimeSupportedImpl();
608: }
609:
610: /**
611: * @see #resetPeakThreadCount()
612: */
613: private native void resetPeakThreadCountImpl();
614:
615: /*
616: * (non-Javadoc)
617: *
618: * @see java.lang.management.ThreadMXBean#resetPeakThreadCount()
619: */
620: public void resetPeakThreadCount() {
621: SecurityManager security = System.getSecurityManager();
622: if (security != null) {
623: security
624: .checkPermission(new ManagementPermission("control"));
625: }
626: this .resetPeakThreadCountImpl();
627: }
628:
629: /**
630: * @param enable
631: * enable thread contention monitoring if <code>true</code>,
632: * otherwise disable thread contention monitoring.
633: */
634: private native void setThreadContentionMonitoringEnabledImpl(
635: boolean enable);
636:
637: /*
638: * (non-Javadoc)
639: *
640: * @see java.lang.management.ThreadMXBean#setThreadContentionMonitoringEnabled(boolean)
641: */
642: public void setThreadContentionMonitoringEnabled(boolean enable) {
643: if (!isThreadContentionMonitoringSupported()) {
644: throw new UnsupportedOperationException(
645: "Thread contention monitoring is not supported on this virtual machine.");
646: }
647:
648: SecurityManager security = System.getSecurityManager();
649: if (security != null) {
650: security
651: .checkPermission(new ManagementPermission("control"));
652: }
653: this .setThreadContentionMonitoringEnabledImpl(enable);
654: }
655:
656: /**
657: * @param enable
658: * enable thread CPU timing if <code>true</code>, otherwise
659: * disable thread CPU timing
660: */
661: private native void setThreadCpuTimeEnabledImpl(boolean enable);
662:
663: /*
664: * (non-Javadoc)
665: *
666: * @see java.lang.management.ThreadMXBean#setThreadCpuTimeEnabled(boolean)
667: */
668: public void setThreadCpuTimeEnabled(boolean enable) {
669: if (!isThreadCpuTimeSupported()) {
670: throw new UnsupportedOperationException(
671: "Thread CPU timing is not supported on this virtual machine.");
672: }
673:
674: SecurityManager security = System.getSecurityManager();
675: if (security != null) {
676: security
677: .checkPermission(new ManagementPermission("control"));
678: }
679: this.setThreadCpuTimeEnabledImpl(enable);
680: }
681: }
|