blob: a62fe80a5f8529ed2ccb4649f64882a075be5baf [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.management;
27
28import java.lang.management.ThreadMXBean;
29
30import java.lang.management.ThreadInfo;
31import java.lang.management.LockInfo;
32import java.lang.management.MonitorInfo;
33import java.util.Map;
34import java.util.HashMap;
35
36/**
37 * Implementation class for the thread subsystem.
38 * Standard and committed hotspot-specific metrics if any.
39 *
40 * ManagementFactory.getThreadMXBean() returns an instance
41 * of this class.
42 */
43class ThreadImpl implements ThreadMXBean {
44
45 private final VMManagement jvm;
46
47 // default for thread contention monitoring is disabled.
48 private boolean contentionMonitoringEnabled = false;
49 private boolean cpuTimeEnabled;
50
51 /**
52 * Constructor of ThreadImpl class.
53 */
54 ThreadImpl(VMManagement vm) {
55 this.jvm = vm;
56 this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled();
57 }
58
59 public int getThreadCount() {
60 return jvm.getLiveThreadCount();
61 }
62
63 public int getPeakThreadCount() {
64 return jvm.getPeakThreadCount();
65 }
66
67 public long getTotalStartedThreadCount() {
68 return jvm.getTotalThreadCount();
69 }
70
71 public int getDaemonThreadCount() {
72 return jvm.getDaemonThreadCount();
73 }
74
75 public boolean isThreadContentionMonitoringSupported() {
76 return jvm.isThreadContentionMonitoringSupported();
77 }
78
79 public synchronized boolean isThreadContentionMonitoringEnabled() {
80 if (!isThreadContentionMonitoringSupported()) {
81 throw new UnsupportedOperationException(
82 "Thread contention monitoring is not supported.");
83 }
84 return contentionMonitoringEnabled;
85 }
86
87 public boolean isThreadCpuTimeSupported() {
88 return jvm.isOtherThreadCpuTimeSupported();
89 }
90
91 public boolean isCurrentThreadCpuTimeSupported() {
92 return jvm.isCurrentThreadCpuTimeSupported();
93 }
94
95 public boolean isThreadCpuTimeEnabled() {
96 if (!isThreadCpuTimeSupported() &&
97 !isCurrentThreadCpuTimeSupported()) {
98 throw new UnsupportedOperationException(
99 "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
171
172 public void setThreadContentionMonitoringEnabled(boolean enable) {
173 if (!isThreadContentionMonitoringSupported()) {
174 throw new UnsupportedOperationException(
175 "Thread contention monitoring is not supported");
176 }
177
178 ManagementFactory.checkControlAccess();
179
180 synchronized (this) {
181 if (contentionMonitoringEnabled != enable) {
182 if (enable) {
183 // if reeabled, reset contention time statistics
184 // for all threads
185 resetContentionTimes0(0);
186 }
187
188 // update the VM of the state change
189 setThreadContentionMonitoringEnabled0(enable);
190
191 contentionMonitoringEnabled = enable;
192 }
193 }
194 }
195
196 public long getCurrentThreadCpuTime() {
197 // check if Thread CPU time measurement is supported.
198 if (!isCurrentThreadCpuTimeSupported()) {
199 throw new UnsupportedOperationException(
200 "Current thread CPU time measurement is not supported.");
201 }
202
203 if (!isThreadCpuTimeEnabled()) {
204 return -1;
205 }
206
207 return getThreadTotalCpuTime0(0);
208 }
209
210 public long getThreadCpuTime(long id) {
211 // check if Thread CPU time measurement is supported.
212 if (!isThreadCpuTimeSupported() &&
213 !isCurrentThreadCpuTimeSupported()) {
214 throw new UnsupportedOperationException(
215 "Thread CPU Time Measurement is not supported.");
216 }
217
218 if (!isThreadCpuTimeSupported()) {
219 // support current thread only
220 if (id != Thread.currentThread().getId()) {
221 throw new UnsupportedOperationException(
222 "Thread CPU Time Measurement is only supported" +
223 " for the current thread.");
224 }
225 }
226
227 if (id <= 0) {
228 throw new IllegalArgumentException(
229 "Invalid thread ID parameter: " + id);
230 }
231
232 if (!isThreadCpuTimeEnabled()) {
233 return -1;
234 }
235
236 if (id == Thread.currentThread().getId()) {
237 // current thread
238 return getThreadTotalCpuTime0(0);
239 } else {
240 return getThreadTotalCpuTime0(id);
241 }
242 }
243
244 public long getCurrentThreadUserTime() {
245 // check if Thread CPU time measurement is supported.
246 if (!isCurrentThreadCpuTimeSupported()) {
247 throw new UnsupportedOperationException(
248 "Current thread CPU time measurement is not supported.");
249 }
250
251 if (!isThreadCpuTimeEnabled()) {
252 return -1;
253 }
254
255 return getThreadUserCpuTime0(0);
256 }
257
258 public long getThreadUserTime(long id) {
259 // check if Thread CPU time measurement is supported.
260 if (!isThreadCpuTimeSupported() &&
261 !isCurrentThreadCpuTimeSupported()) {
262 throw new UnsupportedOperationException(
263 "Thread CPU time measurement is not supported.");
264 }
265
266 if (!isThreadCpuTimeSupported()) {
267 // support current thread only
268 if (id != Thread.currentThread().getId()) {
269 throw new UnsupportedOperationException(
270 "Thread CPU time measurement is only supported" +
271 " for the current thread.");
272 }
273 }
274
275 if (id <= 0) {
276 throw new IllegalArgumentException(
277 "Invalid thread ID parameter: " + id);
278 }
279
280 if (!isThreadCpuTimeEnabled()) {
281 return -1;
282 }
283
284 if (id == Thread.currentThread().getId()) {
285 // current thread
286 return getThreadUserCpuTime0(0);
287 } else {
288 return getThreadUserCpuTime0(id);
289 }
290 }
291
292
293 public void setThreadCpuTimeEnabled(boolean enable) {
294 if (!isThreadCpuTimeSupported() &&
295 !isCurrentThreadCpuTimeSupported()) {
296 throw new UnsupportedOperationException(
297 "Thread CPU time measurement is not supported");
298 }
299
300 ManagementFactory.checkControlAccess();
301 synchronized (this) {
302 if (cpuTimeEnabled != enable) {
303 // update VM of the state change
304 setThreadCpuTimeEnabled0(enable);
305 cpuTimeEnabled = enable;
306 }
307 }
308 }
309
310 public long[] findMonitorDeadlockedThreads() {
311 ManagementFactory.checkMonitorAccess();
312
313 Thread[] threads = findMonitorDeadlockedThreads0();
314 if (threads == null) {
315 return null;
316 }
317
318 long[] ids = new long[threads.length];
319 for (int i = 0; i < threads.length; i++) {
320 Thread t = threads[i];
321 ids[i] = t.getId();
322 }
323 return ids;
324 }
325
326 public long[] findDeadlockedThreads() {
327 if (!isSynchronizerUsageSupported()) {
328 throw new UnsupportedOperationException(
329 "Monitoring of Synchronizer Usage is not supported.");
330 }
331
332 ManagementFactory.checkMonitorAccess();
333
334 Thread[] threads = findDeadlockedThreads0();
335 if (threads == null) {
336 return null;
337 }
338
339 long[] ids = new long[threads.length];
340 for (int i = 0; i < threads.length; i++) {
341 Thread t = threads[i];
342 ids[i] = t.getId();
343 }
344 return ids;
345 }
346
347 public void resetPeakThreadCount() {
348 ManagementFactory.checkControlAccess();
349 resetPeakThreadCount0();
350 }
351
352 public boolean isObjectMonitorUsageSupported() {
353 return jvm.isObjectMonitorUsageSupported();
354 }
355
356 public boolean isSynchronizerUsageSupported() {
357 return jvm.isSynchronizerUsageSupported();
358 }
359
360 public ThreadInfo[] getThreadInfo(long[] ids,
361 boolean lockedMonitors,
362 boolean lockedSynchronizers) {
363 if (ids == null) {
364 throw new NullPointerException("Null ids parameter.");
365 }
366
367 if (lockedMonitors && !isObjectMonitorUsageSupported()) {
368 throw new UnsupportedOperationException(
369 "Monitoring of Object Monitor Usage is not supported.");
370 }
371 if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
372 throw new UnsupportedOperationException(
373 "Monitoring of Synchronizer Usage is not supported.");
374 }
375
376 ManagementFactory.checkMonitorAccess();
377 return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
378 }
379
380
381 public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
382 if (lockedMonitors && !isObjectMonitorUsageSupported()) {
383 throw new UnsupportedOperationException(
384 "Monitoring of Object Monitor Usage is not supported.");
385 }
386 if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
387 throw new UnsupportedOperationException(
388 "Monitoring of Synchronizer Usage is not supported.");
389 }
390
391 ManagementFactory.checkMonitorAccess();
392 return dumpThreads0(null, lockedMonitors, lockedSynchronizers);
393 }
394
395 // VM support where maxDepth == -1 to request entire stack dump
396 private static native Thread[] getThreads();
397 private static native void getThreadInfo0(long[] ids,
398 int maxDepth,
399 ThreadInfo[] result);
400 private static native long getThreadTotalCpuTime0(long id);
401 private static native long getThreadUserCpuTime0(long id);
402 private static native void setThreadCpuTimeEnabled0(boolean enable);
403 private static native void setThreadContentionMonitoringEnabled0(boolean enable);
404 private static native Thread[] findMonitorDeadlockedThreads0();
405 private static native Thread[] findDeadlockedThreads0();
406 private static native void resetPeakThreadCount0();
407 private static native ThreadInfo[] dumpThreads0(long[] ids,
408 boolean lockedMonitors,
409 boolean lockedSynchronizers);
410
411 // tid == 0 to reset contention times for all threads
412 private static native void resetContentionTimes0(long tid);
413}