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