1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.monitor.integration;
15
16 import java.lang.management.ManagementFactory;
17 import java.lang.management.ThreadInfo;
18 import java.lang.management.ThreadMXBean;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.security.Security;
22 import java.util.HashMap;
23 import java.util.Map;
24
25
26
27
28
29
30
31
32 public class JavaMonitorTools
33 {
34 private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
35
36 private static Method findDeadlockMethod = null;
37
38 static
39 {
40 try
41 {
42 findDeadlockMethod = ThreadMXBean.class.getMethod("findDeadlockedThreads");
43 }
44 catch (Exception ignored)
45 {
46
47 try
48 {
49 findDeadlockMethod = ThreadMXBean.class.getMethod("findMonitorDeadlockedThreads");
50 }
51 catch (SecurityException e)
52 {
53 e.printStackTrace();
54 }
55 catch (NoSuchMethodException e)
56 {
57 e.printStackTrace();
58 }
59 }
60 }
61
62 private ThreadInfo[] findDeadlock()
63 throws IllegalAccessException, InvocationTargetException
64 {
65 final long[] threadIds = (long[])findDeadlockMethod.invoke(threadMXBean,(Object[])null);
66
67 if (threadIds == null || threadIds.length < 1)
68 {
69
70 return null;
71 }
72
73 final ThreadInfo[] threads = threadMXBean.getThreadInfo(threadIds,Integer.MAX_VALUE);
74 return threads;
75 }
76
77 public String getDeadlockStacktraces()
78 {
79 try
80 {
81 final ThreadInfo[] threads = findDeadlock();
82 if (threads == null)
83 {
84
85 return null;
86 }
87
88 return stacktraces(threads,0);
89 }
90 catch (Exception e)
91 {
92 return e.getMessage();
93 }
94 }
95
96 private static final int MAX_STACK = 10;
97
98 private String stacktraces(final ThreadInfo[] threads, final int i)
99 {
100 if (i >= threads.length)
101 {
102 return "";
103 }
104 final ThreadInfo thread = threads[i];
105
106 final StringBuilder trace = new StringBuilder();
107 for (int stack_i = 0; stack_i < Math.min(thread.getStackTrace().length,MAX_STACK); stack_i++)
108 {
109 if (stack_i == (MAX_STACK - 1))
110 {
111 trace.append(" ...");
112 }
113 else
114 {
115 trace.append(" at ").append(thread.getStackTrace()[stack_i]).append("\n");
116 }
117 }
118
119 return "\"" + thread.getThreadName() + "\", id " + thread.getThreadId() + " is " + thread.getThreadState() + " on " + thread.getLockName()
120 + ", owned by " + thread.getLockOwnerName() + ", id " + thread.getLockOwnerId() + "\n" + trace + "\n\n" + stacktraces(threads,i + 1);
121 }
122
123
124
125
126
127
128 private long lastSampled = 0L;
129
130 private final Map<Thread.State, Integer> states = new HashMap<Thread.State, Integer>();
131
132 public int getThreadsBlocked()
133 {
134 sampleThreads();
135
136 return states.get(Thread.State.BLOCKED);
137 }
138
139 public int getThreadsNew()
140 {
141 sampleThreads();
142
143 return states.get(Thread.State.NEW);
144 }
145
146 public int getThreadsTerminated()
147 {
148 sampleThreads();
149
150 return states.get(Thread.State.TERMINATED);
151 }
152
153 public int getThreadsTimedWaiting()
154 {
155 sampleThreads();
156
157 return states.get(Thread.State.TIMED_WAITING);
158 }
159
160 public int getThreadsWaiting()
161 {
162 sampleThreads();
163
164 return states.get(Thread.State.WAITING);
165 }
166
167 public int getThreadsRunnable()
168 {
169 sampleThreads();
170
171 return states.get(Thread.State.RUNNABLE);
172 }
173
174 private synchronized void sampleThreads()
175 {
176 if ((lastSampled + 50L) < System.currentTimeMillis())
177 {
178 lastSampled = System.currentTimeMillis();
179 for (final Thread.State state : Thread.State.values())
180 {
181 states.put(state,0);
182 }
183
184 for (final ThreadInfo thread : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds()))
185 {
186 if (thread != null)
187 {
188 final Thread.State state = thread.getThreadState();
189 states.put(state,states.get(state) + 1);
190 }
191 else
192 {
193 states.put(Thread.State.TERMINATED,states.get(Thread.State.TERMINATED) + 1);
194 }
195 }
196 }
197 }
198
199 private static final String POLICY = "sun.net.InetAddressCachePolicy";
200
201 public int getCacheSeconds() throws ClassNotFoundException,
202 IllegalAccessException, InvocationTargetException,
203 NoSuchMethodException {
204 final Class policy = Class.forName(POLICY);
205 final Object returnValue = policy.getMethod("get", (Class[]) null)
206 .invoke(null, (Object[]) null);
207 Integer seconds = (Integer) returnValue;
208
209 return seconds.intValue();
210 }
211
212 public int getCacheNegativeSeconds() throws ClassNotFoundException,
213 IllegalAccessException, InvocationTargetException,
214 NoSuchMethodException {
215 final Class policy = Class.forName(POLICY);
216 final Object returnValue = policy.getMethod("getNegative",
217 (Class[]) null).invoke(null, (Object[]) null);
218 Integer seconds = (Integer) returnValue;
219
220 return seconds.intValue();
221 }
222
223 private static final String DEFAULT = "default";
224
225 private static final String SECURITY = "security";
226
227 private static final String SYSTEM = "system";
228
229 private static final String BOTH = "both";
230
231 private static final String SECURITY_TTL = "networkaddress.cache.ttl";
232
233 private static final String SYSTEM_TTL = "sun.net.inetaddr.ttl";
234
235 private static final String SECURITY_NEGATIVE_TTL = "networkaddress.cache.negative.ttl";
236
237 private static final String SYSTEM_NEGATIVE_TTL = "sun.net.inetaddr.negative.ttl";
238
239 public String getCacheTweakedFrom() {
240 if (Security.getProperty(SECURITY_TTL) != null) {
241 if (System.getProperty(SYSTEM_TTL) != null) {
242 return BOTH;
243 }
244
245 return SECURITY;
246 }
247
248 if (System.getProperty(SYSTEM_TTL) != null) {
249 return SYSTEM;
250 }
251
252 return DEFAULT;
253 }
254
255 public String getCacheNegativeTweakedFrom() {
256 if (Security.getProperty(SECURITY_NEGATIVE_TTL) != null) {
257 if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
258 return BOTH;
259 }
260
261 return SECURITY;
262 }
263
264 if (System.getProperty(SYSTEM_NEGATIVE_TTL) != null) {
265 return SYSTEM;
266 }
267
268 return DEFAULT;
269 }
270 }