| 1 36 37 40 41 import static java.lang.management.ManagementFactory .*; 42 import java.lang.management.ThreadMXBean ; 43 import java.lang.management.ThreadInfo ; 44 import java.lang.management.LockInfo ; 45 import java.lang.management.MonitorInfo ; 46 import javax.management.*; 47 import java.io.*; 48 import java.util.*; 49 50 57 public class ThreadMonitor { 58 private MBeanServerConnection server; 59 private ThreadMXBean tmbean; 60 private ObjectName objname; 61 62 private String findDeadlocksMethodName = "findDeadlockedThreads"; 64 private boolean canDumpLocks = true; 65 66 70 public ThreadMonitor(MBeanServerConnection server) throws IOException { 71 this.server = server; 72 this.tmbean = newPlatformMXBeanProxy(server, 73 THREAD_MXBEAN_NAME, 74 ThreadMXBean .class); 75 try { 76 objname = new ObjectName(THREAD_MXBEAN_NAME); 77 } catch (MalformedObjectNameException e) { 78 InternalError ie = new InternalError (e.getMessage()); 80 ie.initCause(e); 81 throw ie; 82 } 83 parseMBeanInfo(); 84 } 85 86 90 public ThreadMonitor() { 91 this.tmbean = getThreadMXBean(); 92 } 93 94 97 public void threadDump() { 98 if (canDumpLocks) { 99 if (tmbean.isObjectMonitorUsageSupported() && 100 tmbean.isSynchronizerUsageSupported()) { 101 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 [] tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE); 116 for (ThreadInfo ti : tinfos) { 117 printThreadInfo(ti); 118 } 119 } 120 121 124 private void dumpThreadInfoWithLocks() { 125 System.out.println("Full Java thread dump with locks info"); 126 127 ThreadInfo [] tinfos = tmbean.dumpAllThreads(true, true); 128 for (ThreadInfo ti : tinfos) { 129 printThreadInfo(ti); 130 LockInfo [] syncs = ti.getLockedSynchronizers(); 131 printLockInfo(syncs); 132 } 133 System.out.println(); 134 } 135 136 private static String INDENT = " "; 137 138 private void printThreadInfo(ThreadInfo ti) { 139 printThread(ti); 141 142 StackTraceElement [] stacktrace = ti.getStackTrace(); 144 MonitorInfo [] monitors = ti.getLockedMonitors(); 145 for (int i = 0; i < stacktrace.length; i++) { 146 StackTraceElement ste = stacktrace[i]; 147 System.out.println(INDENT + "at " + ste.toString()); 148 for (MonitorInfo 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 ti) { 158 StringBuilder sb = new StringBuilder ("\"" + 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 ti, MonitorInfo [] monitors) { 178 System.out.println(INDENT + "Locked monitors: count = " + monitors.length); 179 for (MonitorInfo 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 [] locks) { 187 System.out.println(INDENT + "Locked synchronizers: count = " + locks.length); 188 for (LockInfo li : locks) { 189 System.out.println(INDENT + " - " + li); 190 } 191 System.out.println(); 192 } 193 194 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 [] infos = tmbean.getThreadInfo(tids, true, true); 209 for (ThreadInfo 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 [] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE); 220 for (ThreadInfo ti : infos) { 221 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 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 findDeadlocksMethodName = "findMonitorDeadlockedThreads"; 247 canDumpLocks = false; 248 } 249 } catch (IntrospectionException e) { 250 InternalError ie = new InternalError (e.getMessage()); 251 ie.initCause(e); 252 throw ie; 253 } catch (InstanceNotFoundException e) { 254 InternalError ie = new InternalError (e.getMessage()); 255 ie.initCause(e); 256 throw ie; 257 } catch (ReflectionException e) { 258 InternalError ie = new InternalError (e.getMessage()); 259 ie.initCause(e); 260 throw ie; 261 } 262 } 263 } 264 | Popular Tags |