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.util.ArrayList;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.TreeMap;
20
21 import org.apache.catalina.Context;
22 import org.springframework.beans.factory.annotation.Value;
23 import org.springframework.stereotype.Controller;
24 import org.springframework.web.bind.annotation.RequestMapping;
25 import org.springframework.web.servlet.ModelAndView;
26
27 import psiprobe.controllers.AbstractTomcatContainerController;
28 import psiprobe.model.java.ThreadModel;
29 import psiprobe.tools.Instruments;
30
31
32
33
34 @Controller
35 public class ListThreadsController extends AbstractTomcatContainerController {
36
37 @RequestMapping(path = "/th_impl1.htm")
38 @Override
39 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
40 throws Exception {
41 return super.handleRequest(request, response);
42 }
43
44 @Override
45 protected ModelAndView handleRequestInternal(HttpServletRequest request,
46 HttpServletResponse response) throws Exception {
47
48
49
50
51
52 List<Context> contexts = getContainerWrapper().getTomcatContainer().findContexts();
53 Map<String, String> classLoaderMap = new TreeMap<>();
54 for (Context context : contexts) {
55 if (context.getLoader() != null && context.getLoader().getClassLoader() != null) {
56 classLoaderMap.put(toUid(context.getLoader().getClassLoader()), context.getName());
57 }
58 }
59
60 return new ModelAndView(getViewName(), "threads", enumerateThreads(classLoaderMap));
61 }
62
63
64
65
66
67
68
69
70 private List<ThreadModel> enumerateThreads(final Map<String, String> classLoaderMap) {
71
72
73 ThreadGroup masterGroup = Thread.currentThread().getThreadGroup();
74 while (masterGroup.getParent() != null) {
75 masterGroup = masterGroup.getParent();
76 }
77
78
79 List<ThreadModel> threadList = new ArrayList<>();
80
81 Thread[] threads = new Thread[masterGroup.activeCount()];
82 int numThreads = masterGroup.enumerate(threads);
83
84 for (int i = 0; i < numThreads; i++) {
85 ThreadModel threadModel = new ThreadModel();
86 threadModel.setThreadClass(threads[i].getClass().getName());
87 threadModel.setName(threads[i].getName());
88 threadModel.setPriority(threads[i].getPriority());
89 threadModel.setDaemon(threads[i].isDaemon());
90 threadModel.setInterrupted(threads[i].isInterrupted());
91 if (threads[i].getThreadGroup() != null) {
92 threadModel.setGroupName(threads[i].getThreadGroup().getName());
93 }
94 Object target = Instruments.getField(threads[i], "target");
95 if (target != null) {
96 threadModel.setRunnableClassName(target.getClass().getName());
97 }
98
99 ClassLoader cl = threads[i].getContextClassLoader();
100 if (cl != null) {
101 if (classLoaderMap != null) {
102 threadModel.setAppName(classLoaderMap.get(toUid(cl)));
103 }
104 threadModel.setClassLoader(toUid(cl));
105 }
106 threadList.add(threadModel);
107 }
108 return threadList;
109 }
110
111
112
113
114
115
116
117
118 private static String toUid(Object obj) {
119 return obj.getClass().getName() + "@" + obj.hashCode();
120 }
121
122 @Value("threads")
123 @Override
124 public void setViewName(String viewName) {
125 super.setViewName(viewName);
126 }
127
128 }