001: /*
002: * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.management;
027:
028: import java.lang.management.ThreadMXBean;
029:
030: import java.lang.management.ThreadInfo;
031: import java.lang.management.LockInfo;
032: import java.lang.management.MonitorInfo;
033: import java.util.Map;
034: import java.util.HashMap;
035:
036: /**
037: * Implementation class for the thread subsystem.
038: * Standard and committed hotspot-specific metrics if any.
039: *
040: * ManagementFactory.getThreadMXBean() returns an instance
041: * of this class.
042: */
043: class ThreadImpl implements ThreadMXBean {
044:
045: private final VMManagement jvm;
046:
047: // default for thread contention monitoring is disabled.
048: private boolean contentionMonitoringEnabled = false;
049: private boolean cpuTimeEnabled;
050:
051: /**
052: * Constructor of ThreadImpl class.
053: */
054: ThreadImpl(VMManagement vm) {
055: this .jvm = vm;
056: this .cpuTimeEnabled = jvm.isThreadCpuTimeEnabled();
057: }
058:
059: public int getThreadCount() {
060: return jvm.getLiveThreadCount();
061: }
062:
063: public int getPeakThreadCount() {
064: return jvm.getPeakThreadCount();
065: }
066:
067: public long getTotalStartedThreadCount() {
068: return jvm.getTotalThreadCount();
069: }
070:
071: public int getDaemonThreadCount() {
072: return jvm.getDaemonThreadCount();
073: }
074:
075: public boolean isThreadContentionMonitoringSupported() {
076: return jvm.isThreadContentionMonitoringSupported();
077: }
078:
079: public synchronized boolean isThreadContentionMonitoringEnabled() {
080: if (!isThreadContentionMonitoringSupported()) {
081: throw new UnsupportedOperationException(
082: "Thread contention monitoring is not supported.");
083: }
084: return contentionMonitoringEnabled;
085: }
086:
087: public boolean isThreadCpuTimeSupported() {
088: return jvm.isOtherThreadCpuTimeSupported();
089: }
090:
091: public boolean isCurrentThreadCpuTimeSupported() {
092: return jvm.isCurrentThreadCpuTimeSupported();
093: }
094:
095: public boolean isThreadCpuTimeEnabled() {
096: if (!isThreadCpuTimeSupported()
097: && !isCurrentThreadCpuTimeSupported()) {
098: throw new UnsupportedOperationException(
099: "Thread CPU time measurement is not supported");
100: }
101: return cpuTimeEnabled;
102: }
103:
104: public long[] getAllThreadIds() {
105: ManagementFactory.checkMonitorAccess();
106:
107: Thread[] threads = getThreads();
108: int length = threads.length;
109: long[] ids = new long[length];
110: for (int i = 0; i < length; i++) {
111: Thread t = threads[i];
112: ids[i] = t.getId();
113: }
114: return ids;
115: }
116:
117: public ThreadInfo getThreadInfo(long id) {
118: if (id <= 0) {
119: throw new IllegalArgumentException(
120: "Invalid thread ID parameter: " + id);
121: }
122:
123: long[] ids = new long[1];
124: ids[0] = id;
125: final ThreadInfo[] infos = getThreadInfo(ids, 0);
126: return infos[0];
127: }
128:
129: public ThreadInfo getThreadInfo(long id, int maxDepth) {
130: if (id <= 0) {
131: throw new IllegalArgumentException(
132: "Invalid thread ID parameter: " + id);
133: }
134: if (maxDepth < 0) {
135: throw new IllegalArgumentException(
136: "Invalid maxDepth parameter: " + maxDepth);
137: }
138:
139: long[] ids = new long[1];
140: ids[0] = id;
141: final ThreadInfo[] infos = getThreadInfo(ids, maxDepth);
142: return infos[0];
143: }
144:
145: public ThreadInfo[] getThreadInfo(long[] ids) {
146: return getThreadInfo(ids, 0);
147: }
148:
149: public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
150: if (ids == null) {
151: throw new NullPointerException("Null ids parameter.");
152: }
153:
154: if (maxDepth < 0) {
155: throw new IllegalArgumentException(
156: "Invalid maxDepth parameter: " + maxDepth);
157: }
158:
159: ManagementFactory.checkMonitorAccess();
160:
161: ThreadInfo[] infos = new ThreadInfo[ids.length];
162: if (maxDepth == Integer.MAX_VALUE) {
163: getThreadInfo0(ids, -1, infos);
164: } else {
165: getThreadInfo0(ids, maxDepth, infos);
166: }
167: return infos;
168: }
169:
170: public void setThreadContentionMonitoringEnabled(boolean enable) {
171: if (!isThreadContentionMonitoringSupported()) {
172: throw new UnsupportedOperationException(
173: "Thread contention monitoring is not supported");
174: }
175:
176: ManagementFactory.checkControlAccess();
177:
178: synchronized (this ) {
179: if (contentionMonitoringEnabled != enable) {
180: if (enable) {
181: // if reeabled, reset contention time statistics
182: // for all threads
183: resetContentionTimes0(0);
184: }
185:
186: // update the VM of the state change
187: setThreadContentionMonitoringEnabled0(enable);
188:
189: contentionMonitoringEnabled = enable;
190: }
191: }
192: }
193:
194: public long getCurrentThreadCpuTime() {
195: // check if Thread CPU time measurement is supported.
196: if (!isCurrentThreadCpuTimeSupported()) {
197: throw new UnsupportedOperationException(
198: "Current thread CPU time measurement is not supported.");
199: }
200:
201: if (!isThreadCpuTimeEnabled()) {
202: return -1;
203: }
204:
205: return getThreadTotalCpuTime0(0);
206: }
207:
208: public long getThreadCpuTime(long id) {
209: // check if Thread CPU time measurement is supported.
210: if (!isThreadCpuTimeSupported()
211: && !isCurrentThreadCpuTimeSupported()) {
212: throw new UnsupportedOperationException(
213: "Thread CPU Time Measurement is not supported.");
214: }
215:
216: if (!isThreadCpuTimeSupported()) {
217: // support current thread only
218: if (id != Thread.currentThread().getId()) {
219: throw new UnsupportedOperationException(
220: "Thread CPU Time Measurement is only supported"
221: + " for the current thread.");
222: }
223: }
224:
225: if (id <= 0) {
226: throw new IllegalArgumentException(
227: "Invalid thread ID parameter: " + id);
228: }
229:
230: if (!isThreadCpuTimeEnabled()) {
231: return -1;
232: }
233:
234: if (id == Thread.currentThread().getId()) {
235: // current thread
236: return getThreadTotalCpuTime0(0);
237: } else {
238: return getThreadTotalCpuTime0(id);
239: }
240: }
241:
242: public long getCurrentThreadUserTime() {
243: // check if Thread CPU time measurement is supported.
244: if (!isCurrentThreadCpuTimeSupported()) {
245: throw new UnsupportedOperationException(
246: "Current thread CPU time measurement is not supported.");
247: }
248:
249: if (!isThreadCpuTimeEnabled()) {
250: return -1;
251: }
252:
253: return getThreadUserCpuTime0(0);
254: }
255:
256: public long getThreadUserTime(long id) {
257: // check if Thread CPU time measurement is supported.
258: if (!isThreadCpuTimeSupported()
259: && !isCurrentThreadCpuTimeSupported()) {
260: throw new UnsupportedOperationException(
261: "Thread CPU time measurement is not supported.");
262: }
263:
264: if (!isThreadCpuTimeSupported()) {
265: // support current thread only
266: if (id != Thread.currentThread().getId()) {
267: throw new UnsupportedOperationException(
268: "Thread CPU time measurement is only supported"
269: + " for the current thread.");
270: }
271: }
272:
273: if (id <= 0) {
274: throw new IllegalArgumentException(
275: "Invalid thread ID parameter: " + id);
276: }
277:
278: if (!isThreadCpuTimeEnabled()) {
279: return -1;
280: }
281:
282: if (id == Thread.currentThread().getId()) {
283: // current thread
284: return getThreadUserCpuTime0(0);
285: } else {
286: return getThreadUserCpuTime0(id);
287: }
288: }
289:
290: public void setThreadCpuTimeEnabled(boolean enable) {
291: if (!isThreadCpuTimeSupported()
292: && !isCurrentThreadCpuTimeSupported()) {
293: throw new UnsupportedOperationException(
294: "Thread CPU time measurement is not supported");
295: }
296:
297: ManagementFactory.checkControlAccess();
298: synchronized (this ) {
299: if (cpuTimeEnabled != enable) {
300: // update VM of the state change
301: setThreadCpuTimeEnabled0(enable);
302: cpuTimeEnabled = enable;
303: }
304: }
305: }
306:
307: public long[] findMonitorDeadlockedThreads() {
308: ManagementFactory.checkMonitorAccess();
309:
310: Thread[] threads = findMonitorDeadlockedThreads0();
311: if (threads == null) {
312: return null;
313: }
314:
315: long[] ids = new long[threads.length];
316: for (int i = 0; i < threads.length; i++) {
317: Thread t = threads[i];
318: ids[i] = t.getId();
319: }
320: return ids;
321: }
322:
323: public long[] findDeadlockedThreads() {
324: if (!isSynchronizerUsageSupported()) {
325: throw new UnsupportedOperationException(
326: "Monitoring of Synchronizer Usage is not supported.");
327: }
328:
329: ManagementFactory.checkMonitorAccess();
330:
331: Thread[] threads = findDeadlockedThreads0();
332: if (threads == null) {
333: return null;
334: }
335:
336: long[] ids = new long[threads.length];
337: for (int i = 0; i < threads.length; i++) {
338: Thread t = threads[i];
339: ids[i] = t.getId();
340: }
341: return ids;
342: }
343:
344: public void resetPeakThreadCount() {
345: ManagementFactory.checkControlAccess();
346: resetPeakThreadCount0();
347: }
348:
349: public boolean isObjectMonitorUsageSupported() {
350: return jvm.isObjectMonitorUsageSupported();
351: }
352:
353: public boolean isSynchronizerUsageSupported() {
354: return jvm.isSynchronizerUsageSupported();
355: }
356:
357: public ThreadInfo[] getThreadInfo(long[] ids,
358: boolean lockedMonitors, boolean lockedSynchronizers) {
359: if (ids == null) {
360: throw new NullPointerException("Null ids parameter.");
361: }
362:
363: if (lockedMonitors && !isObjectMonitorUsageSupported()) {
364: throw new UnsupportedOperationException(
365: "Monitoring of Object Monitor Usage is not supported.");
366: }
367: if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
368: throw new UnsupportedOperationException(
369: "Monitoring of Synchronizer Usage is not supported.");
370: }
371:
372: ManagementFactory.checkMonitorAccess();
373: return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
374: }
375:
376: public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
377: boolean lockedSynchronizers) {
378: if (lockedMonitors && !isObjectMonitorUsageSupported()) {
379: throw new UnsupportedOperationException(
380: "Monitoring of Object Monitor Usage is not supported.");
381: }
382: if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
383: throw new UnsupportedOperationException(
384: "Monitoring of Synchronizer Usage is not supported.");
385: }
386:
387: ManagementFactory.checkMonitorAccess();
388: return dumpThreads0(null, lockedMonitors, lockedSynchronizers);
389: }
390:
391: // VM support where maxDepth == -1 to request entire stack dump
392: private static native Thread[] getThreads();
393:
394: private static native void getThreadInfo0(long[] ids, int maxDepth,
395: ThreadInfo[] result);
396:
397: private static native long getThreadTotalCpuTime0(long id);
398:
399: private static native long getThreadUserCpuTime0(long id);
400:
401: private static native void setThreadCpuTimeEnabled0(boolean enable);
402:
403: private static native void setThreadContentionMonitoringEnabled0(
404: boolean enable);
405:
406: private static native Thread[] findMonitorDeadlockedThreads0();
407:
408: private static native Thread[] findDeadlockedThreads0();
409:
410: private static native void resetPeakThreadCount0();
411:
412: private static native ThreadInfo[] dumpThreads0(long[] ids,
413: boolean lockedMonitors, boolean lockedSynchronizers);
414:
415: // tid == 0 to reset contention times for all threads
416: private static native void resetContentionTimes0(long tid);
417: }
|