Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java @ 3945:8ed53447f690
Merge
author | iveresov |
---|---|
date | Thu, 15 Sep 2011 12:44:09 -0700 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.bugspot; | |
26 | |
27 import java.awt.*; | |
28 import java.awt.event.*; | |
29 import java.util.*; | |
30 import javax.swing.*; | |
31 import javax.swing.table.*; | |
32 | |
33 import sun.jvm.hotspot.debugger.*; | |
34 import sun.jvm.hotspot.debugger.cdbg.*; | |
35 import sun.jvm.hotspot.runtime.*; | |
36 import sun.jvm.hotspot.ui.*; | |
37 | |
38 // NOTE: this class was not placed in sun.jvm.hotspot.ui to prevent | |
39 // mixing components designed for C and C++ debugging with the ones | |
40 // that work with the core serviceability agent functionality (which | |
41 // does not require that the CDebugger interface be implemented). | |
42 | |
43 /** The ThreadListPanel is used for C and C++ debugging and can | |
44 visualize all threads in the target process. The caller passes in | |
45 a CDebugger attached to the target process and can request that | |
46 JavaThreads' associations with these underlying threads be | |
47 displayed; this option is only valid when attached to a HotSpot | |
48 JVM and when the {@link sun.jvm.hotspot.runtime.VM} has been | |
49 initialized. */ | |
50 | |
51 public class ThreadListPanel extends JPanel { | |
52 /** Listener which can be added to receive "Set Focus" events */ | |
53 public static interface Listener { | |
54 /** ThreadProxy will always be provided; JavaThread will only be | |
55 present if displayJavaThreads was specified in the constructor | |
56 for the panel and the thread was a JavaThread. */ | |
57 public void setFocus(ThreadProxy thread, JavaThread jthread); | |
58 } | |
59 | |
60 static class ThreadInfo { | |
61 private ThreadProxy thread; | |
62 // Distinguish between PC == null and no top frame | |
63 private boolean gotPC; | |
64 private Address pc; | |
65 private String location; | |
66 private JavaThread javaThread; | |
67 private String javaThreadName; | |
68 | |
69 public ThreadInfo(ThreadProxy thread, CDebugger dbg, JavaThread jthread) { | |
70 this.thread = thread; | |
71 this.location = "<unknown>"; | |
72 CFrame fr = dbg.topFrameForThread(thread); | |
73 if (fr != null) { | |
74 gotPC = true; | |
75 pc = fr.pc(); | |
76 PCFinder.Info info = PCFinder.findPC(pc, fr.loadObjectForPC(), dbg); | |
77 if (info.getName() != null) { | |
78 location = info.getName(); | |
79 if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) { | |
80 location = location + " (?)"; | |
81 } | |
82 if (info.getOffset() < 0) { | |
83 location = location + " + 0x" + Long.toHexString(info.getOffset()); | |
84 } | |
85 } | |
86 } | |
87 if (jthread != null) { | |
88 javaThread = jthread; | |
89 javaThreadName = jthread.getThreadName(); | |
90 } | |
91 } | |
92 | |
93 public ThreadProxy getThread() { return thread; } | |
94 public boolean hasPC() { return gotPC; } | |
95 public Address getPC() { return pc; } | |
96 public String getLocation() { return location; } | |
97 public boolean isJavaThread() { return (javaThread != null); } | |
98 public JavaThread getJavaThread() { return javaThread; } | |
99 public String getJavaThreadName() { return javaThreadName; } | |
100 } | |
101 | |
102 // List<ThreadInfo> | |
103 private java.util.List threadList; | |
104 private JTable table; | |
105 private AbstractTableModel dataModel; | |
106 // List<Listener> | |
107 private java.util.List listeners; | |
108 | |
109 /** Takes a CDebugger from which the thread list is queried. | |
110 displayJavaThreads must only be set to true if the debugger is | |
111 attached to a HotSpot JVM and if the VM has already been | |
112 initialized. */ | |
113 public ThreadListPanel(CDebugger dbg, final boolean displayJavaThreads) { | |
114 super(); | |
115 | |
116 Map threadToJavaThreadMap = null; | |
117 if (displayJavaThreads) { | |
118 // Collect Java threads from virtual machine and insert them in | |
119 // table for later querying | |
120 threadToJavaThreadMap = new HashMap(); | |
121 Threads threads = VM.getVM().getThreads(); | |
122 for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) { | |
123 threadToJavaThreadMap.put(thr.getThreadProxy(), thr); | |
124 } | |
125 } | |
126 | |
127 java.util.List/*<ThreadProxy>*/ threads = dbg.getThreadList(); | |
128 threadList = new ArrayList(threads.size()); | |
129 for (Iterator iter = threads.iterator(); iter.hasNext(); ) { | |
130 ThreadProxy thr = (ThreadProxy) iter.next(); | |
131 JavaThread jthr = null; | |
132 if (displayJavaThreads) { | |
133 jthr = (JavaThread) threadToJavaThreadMap.get(thr); | |
134 } | |
135 threadList.add(new ThreadInfo(thr, dbg, jthr)); | |
136 } | |
137 | |
138 // Thread ID, current PC, current symbol, Java Thread, [Java thread name] | |
139 dataModel = new AbstractTableModel() { | |
140 public int getColumnCount() { return (displayJavaThreads ? 5 : 3); } | |
141 public int getRowCount() { return threadList.size(); } | |
142 public String getColumnName(int col) { | |
143 switch (col) { | |
144 case 0: | |
145 return "Thread ID"; | |
146 case 1: | |
147 return "PC"; | |
148 case 2: | |
149 return "Location"; | |
150 case 3: | |
151 return "Java?"; | |
152 case 4: | |
153 return "Java Thread Name"; | |
154 default: | |
155 throw new RuntimeException("Index " + col + " out of bounds"); | |
156 } | |
157 } | |
158 public Object getValueAt(int row, int col) { | |
159 ThreadInfo info = (ThreadInfo) threadList.get(row); | |
160 | |
161 switch (col) { | |
162 case 0: | |
163 return info.getThread(); | |
164 case 1: | |
165 { | |
166 if (info.hasPC()) { | |
167 return info.getPC(); | |
168 } | |
169 return "<no frames on stack>"; | |
170 } | |
171 case 2: | |
172 return info.getLocation(); | |
173 case 3: | |
174 if (info.isJavaThread()) { | |
175 return "Yes"; | |
176 } else { | |
177 return ""; | |
178 } | |
179 case 4: | |
180 if (info.isJavaThread()) { | |
181 return info.getJavaThreadName(); | |
182 } else { | |
183 return ""; | |
184 } | |
185 default: | |
186 throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds"); | |
187 } | |
188 } | |
189 }; | |
190 | |
191 // Build user interface | |
192 setLayout(new BorderLayout()); | |
193 table = new JTable(dataModel); | |
194 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | |
195 JTableHeader header = table.getTableHeader(); | |
196 header.setReorderingAllowed(false); | |
197 table.setRowSelectionAllowed(true); | |
198 table.setColumnSelectionAllowed(false); | |
199 JScrollPane scrollPane = new JScrollPane(table); | |
200 add(scrollPane, BorderLayout.CENTER); | |
201 if (threadList.size() > 0) { | |
202 table.setRowSelectionInterval(0, 0); | |
203 } | |
204 | |
205 JButton button = new JButton("Set Focus"); | |
206 button.addActionListener(new ActionListener() { | |
207 public void actionPerformed(ActionEvent e) { | |
208 int i = table.getSelectedRow(); | |
209 if (i < 0) { | |
210 return; | |
211 } | |
212 ThreadInfo info = (ThreadInfo) threadList.get(i); | |
213 for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { | |
214 ((Listener) iter.next()).setFocus(info.getThread(), info.getJavaThread()); | |
215 } | |
216 } | |
217 }); | |
218 JPanel focusPanel = new JPanel(); | |
219 focusPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); | |
220 focusPanel.setLayout(new BoxLayout(focusPanel, BoxLayout.Y_AXIS)); | |
221 focusPanel.add(Box.createGlue()); | |
222 focusPanel.add(button); | |
223 focusPanel.add(Box.createGlue()); | |
224 add(focusPanel, BorderLayout.EAST); | |
225 | |
226 // FIXME: make listener model for the debugger so if the user | |
227 // specifies a mapfile for or path to a given DSO later we can | |
228 // update our state | |
229 } | |
230 | |
231 public void addListener(Listener l) { | |
232 if (listeners == null) { | |
233 listeners = new ArrayList(); | |
234 } | |
235 listeners.add(l); | |
236 } | |
237 } |