KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ThreadMonitor


1 /*
2  * @(#)ThreadMonitor.java 1.6 05/12/22
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * -Redistribution of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * -Redistribution in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17  * be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed, licensed or intended
33  * for use in the design, construction, operation or maintenance of any
34  * nuclear facility.
35  */

36
37 /*
38  * @(#)ThreadMonitor.java 1.6 05/12/22
39  */

40
41 import static java.lang.management.ManagementFactory JavaDoc.*;
42 import java.lang.management.ThreadMXBean JavaDoc;
43 import java.lang.management.ThreadInfo JavaDoc;
44 import java.lang.management.LockInfo JavaDoc;
45 import java.lang.management.MonitorInfo JavaDoc;
46 import javax.management.*;
47 import java.io.*;
48 import java.util.*;
49
50 /**
51  * Example of using the java.lang.management API to dump stack trace
52  * and to perform deadlock detection.
53  *
54  * @author Mandy Chung
55  * @version %% 12/22/05
56  */

57 public class ThreadMonitor {
58     private MBeanServerConnection server;
59     private ThreadMXBean JavaDoc tmbean;
60     private ObjectName objname;
61
62     // default - JDK 6+ VM
63
private String JavaDoc findDeadlocksMethodName = "findDeadlockedThreads";
64     private boolean canDumpLocks = true;
65
66     /**
67      * Constructs a ThreadMonitor object to get thread information
68      * in a remote JVM.
69      */

70     public ThreadMonitor(MBeanServerConnection server) throws IOException {
71        this.server = server;
72        this.tmbean = newPlatformMXBeanProxy(server,
73                                             THREAD_MXBEAN_NAME,
74                                             ThreadMXBean JavaDoc.class);
75        try {
76            objname = new ObjectName(THREAD_MXBEAN_NAME);
77         } catch (MalformedObjectNameException e) {
78             // should not reach here
79
InternalError JavaDoc ie = new InternalError JavaDoc(e.getMessage());
80             ie.initCause(e);
81             throw ie;
82        }
83        parseMBeanInfo();
84     }
85
86     /**
87      * Constructs a ThreadMonitor object to get thread information
88      * in the local JVM.
89      */

90     public ThreadMonitor() {
91         this.tmbean = getThreadMXBean();
92     }
93
94     /**
95      * Prints the thread dump information to System.out.
96      */

97     public void threadDump() {
98         if (canDumpLocks) {
99             if (tmbean.isObjectMonitorUsageSupported() &&
100                 tmbean.isSynchronizerUsageSupported()) {
101                 // Print lock info if both object monitor usage
102
// and synchronizer usage are supported.
103
// This sample code can be modified to handle if
104
// either monitor usage or synchronizer usage is supported.
105
dumpThreadInfoWithLocks();
106             }
107         } else {
108             dumpThreadInfo();
109         }
110     }
111
112     private void dumpThreadInfo() {
113        System.out.println("Full Java thread dump");
114        long[] tids = tmbean.getAllThreadIds();
115        ThreadInfo JavaDoc[] tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
116        for (ThreadInfo JavaDoc ti : tinfos) {
117            printThreadInfo(ti);
118        }
119     }
120
121     /**
122      * Prints the thread dump information with locks info to System.out.
123      */

124     private void dumpThreadInfoWithLocks() {
125        System.out.println("Full Java thread dump with locks info");
126
127        ThreadInfo JavaDoc[] tinfos = tmbean.dumpAllThreads(true, true);
128        for (ThreadInfo JavaDoc ti : tinfos) {
129            printThreadInfo(ti);
130            LockInfo JavaDoc[] syncs = ti.getLockedSynchronizers();
131            printLockInfo(syncs);
132        }
133        System.out.println();
134     }
135
136     private static String JavaDoc INDENT = " ";
137
138     private void printThreadInfo(ThreadInfo JavaDoc ti) {
139        // print thread information
140
printThread(ti);
141
142        // print stack trace with locks
143
StackTraceElement JavaDoc[] stacktrace = ti.getStackTrace();
144        MonitorInfo JavaDoc[] monitors = ti.getLockedMonitors();
145        for (int i = 0; i < stacktrace.length; i++) {
146            StackTraceElement JavaDoc ste = stacktrace[i];
147            System.out.println(INDENT + "at " + ste.toString());
148            for (MonitorInfo JavaDoc mi : monitors) {
149                if (mi.getLockedStackDepth() == i) {
150                    System.out.println(INDENT + " - locked " + mi);
151                }
152            }
153        }
154        System.out.println();
155     }
156                                                                                 
157     private void printThread(ThreadInfo JavaDoc ti) {
158        StringBuilder JavaDoc sb = new StringBuilder JavaDoc("\"" + ti.getThreadName() + "\"" +
159                                             " Id=" + ti.getThreadId() +
160                                             " in " + ti.getThreadState());
161        if (ti.getLockName() != null) {
162            sb.append(" on lock=" + ti.getLockName());
163        }
164        if (ti.isSuspended()) {
165            sb.append(" (suspended)");
166        }
167        if (ti.isInNative()) {
168            sb.append(" (running in native)");
169        }
170        System.out.println(sb.toString());
171        if (ti.getLockOwnerName() != null) {
172             System.out.println(INDENT + " owned by " + ti.getLockOwnerName() +
173                                " Id=" + ti.getLockOwnerId());
174        }
175     }
176
177     private void printMonitorInfo(ThreadInfo JavaDoc ti, MonitorInfo JavaDoc[] monitors) {
178        System.out.println(INDENT + "Locked monitors: count = " + monitors.length);
179        for (MonitorInfo JavaDoc mi : monitors) {
180            System.out.println(INDENT + " - " + mi + " locked at ");
181            System.out.println(INDENT + " " + mi.getLockedStackDepth() +
182                               " " + mi.getLockedStackFrame());
183        }
184     }
185                                                                                 
186     private void printLockInfo(LockInfo JavaDoc[] locks) {
187        System.out.println(INDENT + "Locked synchronizers: count = " + locks.length);
188        for (LockInfo JavaDoc li : locks) {
189            System.out.println(INDENT + " - " + li);
190        }
191        System.out.println();
192     }
193
194     /**
195      * Checks if any threads are deadlocked. If any, print
196      * the thread dump information.
197      */

198     public boolean findDeadlock() {
199        long[] tids;
200        if (findDeadlocksMethodName.equals("findDeadlockedThreads") &&
201                tmbean.isSynchronizerUsageSupported()) {
202            tids = tmbean.findDeadlockedThreads();
203            if (tids == null) {
204                return false;
205            }
206
207            System.out.println("Deadlock found :-");
208            ThreadInfo JavaDoc[] infos = tmbean.getThreadInfo(tids, true, true);
209            for (ThreadInfo JavaDoc ti : infos) {
210                printThreadInfo(ti);
211                printLockInfo(ti.getLockedSynchronizers());
212                System.out.println();
213            }
214        } else {
215            tids = tmbean.findMonitorDeadlockedThreads();
216            if (tids == null) {
217                return false;
218            }
219            ThreadInfo JavaDoc[] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
220            for (ThreadInfo JavaDoc ti : infos) {
221                // print thread information
222
printThreadInfo(ti);
223            }
224        }
225
226        return true;
227     }
228
229
230     private void parseMBeanInfo() throws IOException {
231         try {
232             MBeanOperationInfo[] mopis = server.getMBeanInfo(objname).getOperations();
233
234             // look for findDeadlockedThreads operations;
235
boolean found = false;
236             for (MBeanOperationInfo op : mopis) {
237                 if (op.getName().equals(findDeadlocksMethodName)) {
238                     found = true;
239                     break;
240                 }
241             }
242             if (!found) {
243                 // if findDeadlockedThreads operation doesn't exist,
244
// the target VM is running on JDK 5 and details about
245
// synchronizers and locks cannot be dumped.
246
findDeadlocksMethodName = "findMonitorDeadlockedThreads";
247                 canDumpLocks = false;
248             }
249         } catch (IntrospectionException e) {
250             InternalError JavaDoc ie = new InternalError JavaDoc(e.getMessage());
251             ie.initCause(e);
252             throw ie;
253         } catch (InstanceNotFoundException e) {
254             InternalError JavaDoc ie = new InternalError JavaDoc(e.getMessage());
255             ie.initCause(e);
256             throw ie;
257         } catch (ReflectionException e) {
258             InternalError JavaDoc ie = new InternalError JavaDoc(e.getMessage());
259             ie.initCause(e);
260             throw ie;
261         }
262     }
263 }
264
Popular Tags