1
2
3
4
5
6
7
8
9
10
11 package psiprobe.controllers.threads;
12
13 import jakarta.servlet.http.HttpServletRequest;
14 import jakarta.servlet.http.HttpServletResponse;
15
16 import java.lang.management.ManagementFactory;
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import javax.management.MBeanServer;
21 import javax.management.MalformedObjectNameException;
22 import javax.management.ObjectName;
23 import javax.management.openmbean.CompositeData;
24
25 import org.springframework.beans.factory.annotation.Value;
26 import org.springframework.stereotype.Controller;
27 import org.springframework.web.bind.annotation.RequestMapping;
28 import org.springframework.web.servlet.ModelAndView;
29 import org.springframework.web.servlet.mvc.ParameterizableViewController;
30
31 import psiprobe.model.SunThread;
32 import psiprobe.model.ThreadStackElement;
33 import psiprobe.tools.JmxTools;
34
35
36
37
38 @Controller
39 public class ListSunThreadsController extends ParameterizableViewController {
40
41 @RequestMapping(path = "/th_impl2.htm")
42 @Override
43 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
44 throws Exception {
45 return super.handleRequest(request, response);
46 }
47
48 @Override
49 protected ModelAndView handleRequestInternal(HttpServletRequest request,
50 HttpServletResponse response) throws MalformedObjectNameException {
51
52 List<SunThread> threads = null;
53 int executionStackDepth = 1;
54
55 MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
56 ObjectName objectNameThreading = new ObjectName("java.lang:type=Threading");
57
58 long[] deadlockedIds = (long[]) JmxTools.invoke(mbeanServer, objectNameThreading,
59 "findMonitorDeadlockedThreads", null, null);
60 long[] allIds =
61 (long[]) JmxTools.getAttribute(mbeanServer, objectNameThreading, "AllThreadIds");
62
63 if (allIds != null) {
64 threads = new ArrayList<>(allIds.length);
65
66 for (long id : allIds) {
67 CompositeData cd = (CompositeData) JmxTools.invoke(mbeanServer, objectNameThreading,
68 "getThreadInfo", new Object[] {id, executionStackDepth}, new String[] {"long", "int"});
69
70 if (cd != null) {
71 SunThread st = new SunThread();
72 st.setId(JmxTools.getLongAttr(cd, "threadId"));
73 st.setName(JmxTools.getStringAttr(cd, "threadName"));
74 st.setState(JmxTools.getStringAttr(cd, "threadState"));
75 st.setSuspended(JmxTools.getBooleanAttr(cd, "suspended"));
76 st.setInNative(JmxTools.getBooleanAttr(cd, "inNative"));
77 st.setLockName(JmxTools.getStringAttr(cd, "lockName"));
78 st.setLockOwnerName(JmxTools.getStringAttr(cd, "lockOwnerName"));
79 st.setWaitedCount(JmxTools.getLongAttr(cd, "waitedCount"));
80 st.setBlockedCount(JmxTools.getLongAttr(cd, "blockedCount"));
81 st.setDeadlocked(contains(deadlockedIds, st.getId()));
82
83 CompositeData[] stack = (CompositeData[]) cd.get("stackTrace");
84 if (stack.length > 0) {
85 CompositeData cd2 = stack[0];
86 ThreadStackElement tse = new ThreadStackElement();
87 tse.setClassName(JmxTools.getStringAttr(cd2, "className"));
88 tse.setFileName(JmxTools.getStringAttr(cd2, "fileName"));
89 tse.setMethodName(JmxTools.getStringAttr(cd2, "methodName"));
90 tse.setLineNumber(JmxTools.getIntAttr(cd2, "lineNumber", -1));
91 tse.setNativeMethod(JmxTools.getBooleanAttr(cd2, "nativeMethod"));
92 st.setExecutionPoint(tse);
93 }
94
95 threads.add(st);
96 }
97 }
98 }
99 return new ModelAndView(getViewName(), "threads", threads);
100 }
101
102
103
104
105
106
107
108
109
110 private static boolean contains(long[] haystack, long needle) {
111 if (haystack != null) {
112 for (long hay : haystack) {
113 if (hay == needle) {
114 return true;
115 }
116 }
117 }
118 return false;
119 }
120
121 @Value("threads_sun")
122 @Override
123 public void setViewName(String viewName) {
124 super.setViewName(viewName);
125 }
126
127 }