Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HSDB.java @ 19491:4d66c000d253
Truffle/Instrumentation: more cleanup in Probe
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Wed, 18 Feb 2015 18:30:49 -0800 |
parents | 89152779163c |
children |
rev | line source |
---|---|
0 | 1 /* |
17524 | 2 * Copyright (c) 2000, 2013, 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:
1385
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
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:
1385
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot; | |
26 | |
27 import java.io.*; | |
28 import java.awt.*; | |
29 import java.awt.event.*; | |
30 import java.math.*; | |
31 import javax.swing.*; | |
32 import javax.swing.tree.*; | |
33 import java.util.*; | |
34 | |
35 import sun.jvm.hotspot.code.*; | |
36 import sun.jvm.hotspot.compiler.*; | |
37 import sun.jvm.hotspot.debugger.*; | |
38 import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; | |
39 import sun.jvm.hotspot.gc_interface.*; | |
40 import sun.jvm.hotspot.interpreter.*; | |
41 import sun.jvm.hotspot.memory.*; | |
42 import sun.jvm.hotspot.oops.*; | |
43 import sun.jvm.hotspot.runtime.*; | |
44 import sun.jvm.hotspot.ui.*; | |
45 import sun.jvm.hotspot.ui.tree.*; | |
46 import sun.jvm.hotspot.ui.classbrowser.*; | |
47 import sun.jvm.hotspot.utilities.*; | |
48 | |
49 /** The top-level HotSpot Debugger. FIXME: make this an embeddable | |
50 component! (Among other things, figure out what to do with the | |
51 menu bar...) */ | |
52 | |
53 public class HSDB implements ObjectHistogramPanel.Listener, SAListener { | |
54 public static void main(String[] args) { | |
55 new HSDB(args).run(); | |
56 } | |
57 | |
58 //-------------------------------------------------------------------------------- | |
59 // Internals only below this point | |
60 // | |
61 private HotSpotAgent agent; | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
62 private JVMDebugger jvmDebugger; |
0 | 63 private JDesktopPane desktop; |
64 private boolean attached; | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
65 private boolean argError; |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
66 private JFrame frame; |
0 | 67 /** List <JMenuItem> */ |
68 private java.util.List attachMenuItems; | |
69 /** List <JMenuItem> */ | |
70 private java.util.List detachMenuItems; | |
71 private JMenu toolsMenu; | |
72 private JMenuItem showDbgConsoleMenuItem; | |
73 private JMenuItem computeRevPtrsMenuItem; | |
74 private JInternalFrame attachWaitDialog; | |
75 private JInternalFrame threadsFrame; | |
76 private JInternalFrame consoleFrame; | |
77 private WorkerThread workerThread; | |
78 // These had to be made data members because they are referenced in inner classes. | |
79 private String pidText; | |
80 private int pid; | |
81 private String execPath; | |
82 private String coreFilename; | |
83 | |
84 private void doUsage() { | |
85 System.out.println("Usage: java HSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]"); | |
86 System.out.println(" pid: attach to the process whose id is 'pid'"); | |
87 System.out.println(" path-to-java-executable: Debug a core file produced by this program"); | |
88 System.out.println(" path-to-corefile: Debug this corefile. The default is 'core'"); | |
89 System.out.println(" If no arguments are specified, you can select what to do from the GUI.\n"); | |
90 HotSpotAgent.showUsage(); | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
91 argError = true; |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
92 } |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
93 |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
94 public HSDB(JVMDebugger d) { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
95 jvmDebugger = d; |
0 | 96 } |
97 | |
98 private HSDB(String[] args) { | |
99 switch (args.length) { | |
100 case (0): | |
101 break; | |
102 | |
103 case (1): | |
104 if (args[0].equals("help") || args[0].equals("-help")) { | |
105 doUsage(); | |
106 } | |
107 // If all numbers, it is a PID to attach to | |
108 // Else, it is a pathname to a .../bin/java for a core file. | |
109 try { | |
110 int unused = Integer.parseInt(args[0]); | |
111 // If we get here, we have a PID and not a core file name | |
112 pidText = args[0]; | |
113 } catch (NumberFormatException e) { | |
114 execPath = args[0]; | |
115 coreFilename = "core"; | |
116 } | |
117 break; | |
118 | |
119 case (2): | |
120 execPath = args[0]; | |
121 coreFilename = args[1]; | |
122 break; | |
123 | |
124 default: | |
125 System.out.println("HSDB Error: Too many options specified"); | |
126 doUsage(); | |
127 } | |
128 } | |
129 | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
130 // close this tool without calling System.exit |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
131 protected void closeUI() { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
132 workerThread.shutdown(); |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
133 frame.dispose(); |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
134 } |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
135 |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
136 public void run() { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
137 // Don't start the UI if there were bad arguments. |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
138 if (argError) { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
139 return; |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
140 } |
0 | 141 |
142 agent = new HotSpotAgent(); | |
143 workerThread = new WorkerThread(); | |
144 attachMenuItems = new java.util.ArrayList(); | |
145 detachMenuItems = new java.util.ArrayList(); | |
146 | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
147 frame = new JFrame("HSDB - HotSpot Debugger"); |
0 | 148 frame.setSize(800, 600); |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
149 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); |
0 | 150 |
151 JMenuBar menuBar = new JMenuBar(); | |
152 | |
153 // | |
154 // File menu | |
155 // | |
156 | |
157 JMenu menu = new JMenu("File"); | |
158 menu.setMnemonic(KeyEvent.VK_F); | |
159 JMenuItem item; | |
160 item = createMenuItem("Attach to HotSpot process...", | |
161 new ActionListener() { | |
162 public void actionPerformed(ActionEvent e) { | |
163 showAttachDialog(); | |
164 } | |
165 }); | |
166 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK)); | |
167 item.setMnemonic(KeyEvent.VK_A); | |
168 menu.add(item); | |
169 attachMenuItems.add(item); | |
170 | |
171 item = createMenuItem("Open HotSpot core file...", | |
172 new ActionListener() { | |
173 public void actionPerformed(ActionEvent e) { | |
174 showOpenCoreFileDialog(); | |
175 } | |
176 }); | |
177 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK)); | |
178 item.setMnemonic(KeyEvent.VK_O); | |
179 menu.add(item); | |
180 attachMenuItems.add(item); | |
181 | |
182 item = createMenuItem("Connect to debug server...", | |
183 new ActionListener() { | |
184 public void actionPerformed(ActionEvent e) { | |
185 showConnectDialog(); | |
186 } | |
187 }); | |
188 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.ALT_MASK)); | |
189 item.setMnemonic(KeyEvent.VK_S); | |
190 menu.add(item); | |
191 attachMenuItems.add(item); | |
192 | |
193 item = createMenuItem("Detach", | |
194 new ActionListener() { | |
195 public void actionPerformed(ActionEvent e) { | |
196 detach(); | |
197 } | |
198 }); | |
199 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK)); | |
200 item.setMnemonic(KeyEvent.VK_S); | |
201 menu.add(item); | |
202 detachMenuItems.add(item); | |
203 | |
204 // Disable detach menu items at first | |
205 setMenuItemsEnabled(detachMenuItems, false); | |
206 | |
207 menu.addSeparator(); | |
208 | |
209 item = createMenuItem("Exit", | |
210 new ActionListener() { | |
211 public void actionPerformed(ActionEvent e) { | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
212 closeUI(); |
0 | 213 } |
214 }); | |
215 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK)); | |
216 item.setMnemonic(KeyEvent.VK_X); | |
217 menu.add(item); | |
218 menuBar.add(menu); | |
219 | |
220 // | |
221 // Tools menu | |
222 // | |
223 | |
224 toolsMenu = new JMenu("Tools"); | |
225 toolsMenu.setMnemonic(KeyEvent.VK_T); | |
226 | |
227 item = createMenuItem("Class Browser", | |
228 new ActionListener() { | |
229 public void actionPerformed(ActionEvent e) { | |
230 showClassBrowser(); | |
231 } | |
232 }); | |
233 item.setMnemonic(KeyEvent.VK_B); | |
234 | |
235 toolsMenu.add(item); | |
236 | |
237 item = createMenuItem("Code Viewer", | |
238 new ActionListener() { | |
239 public void actionPerformed(ActionEvent e) { | |
240 showCodeViewer(); | |
241 } | |
242 }); | |
243 item.setMnemonic(KeyEvent.VK_C); | |
244 | |
245 toolsMenu.add(item); | |
246 | |
247 | |
248 item = createMenuItem("Compute Reverse Ptrs", | |
249 new ActionListener() { | |
250 public void actionPerformed(ActionEvent e) { | |
251 fireComputeReversePtrs(); | |
252 } | |
253 }); | |
254 computeRevPtrsMenuItem = item; | |
255 item.setMnemonic(KeyEvent.VK_M); | |
256 toolsMenu.add(item); | |
257 | |
258 item = createMenuItem("Deadlock Detection", | |
259 new ActionListener() { | |
260 public void actionPerformed(ActionEvent e) { | |
261 showDeadlockDetectionPanel(); | |
262 } | |
263 }); | |
264 item.setMnemonic(KeyEvent.VK_D); | |
265 toolsMenu.add(item); | |
266 | |
267 item = createMenuItem("Find Object by Query", | |
268 new ActionListener() { | |
269 public void actionPerformed(ActionEvent e) { | |
270 showFindByQueryPanel(); | |
271 } | |
272 }); | |
273 item.setMnemonic(KeyEvent.VK_Q); | |
274 toolsMenu.add(item); | |
275 | |
276 | |
277 item = createMenuItem("Find Pointer", | |
278 new ActionListener() { | |
279 public void actionPerformed(ActionEvent e) { | |
280 showFindPanel(); | |
281 } | |
282 }); | |
283 item.setMnemonic(KeyEvent.VK_P); | |
284 toolsMenu.add(item); | |
285 | |
286 item = createMenuItem("Find Value In Heap", | |
287 new ActionListener() { | |
288 public void actionPerformed(ActionEvent e) { | |
289 showFindInHeapPanel(); | |
290 } | |
291 }); | |
292 item.setMnemonic(KeyEvent.VK_V); | |
293 toolsMenu.add(item); | |
294 | |
295 item = createMenuItem("Find Value In Code Cache", | |
296 new ActionListener() { | |
297 public void actionPerformed(ActionEvent e) { | |
298 showFindInCodeCachePanel(); | |
299 } | |
300 }); | |
301 item.setMnemonic(KeyEvent.VK_A); | |
302 toolsMenu.add(item); | |
303 | |
304 item = createMenuItem("Heap Parameters", | |
305 new ActionListener() { | |
306 public void actionPerformed(ActionEvent e) { | |
307 showHeapParametersPanel(); | |
308 } | |
309 }); | |
310 item.setMnemonic(KeyEvent.VK_H); | |
311 toolsMenu.add(item); | |
312 | |
313 item = createMenuItem("Inspector", | |
314 new ActionListener() { | |
315 public void actionPerformed(ActionEvent e) { | |
316 showInspector(null); | |
317 } | |
318 }); | |
319 item.setMnemonic(KeyEvent.VK_R); | |
320 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK)); | |
321 toolsMenu.add(item); | |
322 | |
323 item = createMenuItem("Memory Viewer", | |
324 new ActionListener() { | |
325 public void actionPerformed(ActionEvent e) { | |
326 showMemoryViewer(); | |
327 } | |
328 }); | |
329 item.setMnemonic(KeyEvent.VK_M); | |
330 toolsMenu.add(item); | |
331 | |
332 item = createMenuItem("Monitor Cache Dump", | |
333 new ActionListener() { | |
334 public void actionPerformed(ActionEvent e) { | |
335 showMonitorCacheDumpPanel(); | |
336 } | |
337 }); | |
338 item.setMnemonic(KeyEvent.VK_D); | |
339 toolsMenu.add(item); | |
340 | |
341 item = createMenuItem("Object Histogram", | |
342 new ActionListener() { | |
343 public void actionPerformed(ActionEvent e) { | |
344 showObjectHistogram(); | |
345 } | |
346 }); | |
347 item.setMnemonic(KeyEvent.VK_O); | |
348 toolsMenu.add(item); | |
349 | |
350 item = createMenuItem("Show System Properties", | |
351 new ActionListener() { | |
352 public void actionPerformed(ActionEvent e) { | |
353 showSystemProperties(); | |
354 } | |
355 }); | |
356 item.setMnemonic(KeyEvent.VK_S); | |
357 toolsMenu.add(item); | |
358 | |
359 item = createMenuItem("Show VM Version", | |
360 new ActionListener() { | |
361 public void actionPerformed(ActionEvent e) { | |
362 showVMVersion(); | |
363 } | |
364 }); | |
365 item.setMnemonic(KeyEvent.VK_M); | |
366 toolsMenu.add(item); | |
367 | |
368 item = createMenuItem("Show -XX flags", | |
369 new ActionListener() { | |
370 public void actionPerformed(ActionEvent e) { | |
371 showCommandLineFlags(); | |
372 } | |
373 }); | |
374 item.setMnemonic(KeyEvent.VK_X); | |
375 toolsMenu.add(item); | |
376 | |
377 toolsMenu.setEnabled(false); | |
378 menuBar.add(toolsMenu); | |
379 | |
380 // | |
381 // Windows menu | |
382 // | |
383 | |
384 JMenu windowsMenu = new JMenu("Windows"); | |
385 windowsMenu.setMnemonic(KeyEvent.VK_W); | |
386 item = createMenuItem("Console", | |
387 new ActionListener() { | |
388 public void actionPerformed(ActionEvent e) { | |
389 showConsole(); | |
390 } | |
391 }); | |
392 item.setMnemonic(KeyEvent.VK_C); | |
393 windowsMenu.add(item); | |
394 showDbgConsoleMenuItem = createMenuItem("Debugger Console", | |
395 new ActionListener() { | |
396 public void actionPerformed(ActionEvent e) { | |
397 showDebuggerConsole(); | |
398 } | |
399 }); | |
400 showDbgConsoleMenuItem.setMnemonic(KeyEvent.VK_D); | |
401 windowsMenu.add(showDbgConsoleMenuItem); | |
402 showDbgConsoleMenuItem.setEnabled(false); | |
403 | |
404 menuBar.add(windowsMenu); | |
405 | |
406 | |
407 frame.setJMenuBar(menuBar); | |
408 | |
409 desktop = new JDesktopPane(); | |
410 frame.getContentPane().add(desktop); | |
411 GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize()); | |
412 GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize()); | |
152
c70a245cad3a
6670684: 4/5 SA command universe did not print out CMS space information
dcubed
parents:
0
diff
changeset
|
413 frame.setVisible(true); |
0 | 414 |
415 Runtime.getRuntime().addShutdownHook(new java.lang.Thread() { | |
416 public void run() { | |
417 detachDebugger(); | |
418 } | |
419 }); | |
420 | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
421 // If jvmDebugger is already set, we have been given a JVMDebugger. |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
422 // Otherwise, if pidText != null we are supposed to attach to it. |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
423 // Finally, if execPath != null, it is the path of a jdk/bin/java |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
424 // and coreFilename is the pathname of a core file we are |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
425 // supposed to attach to. |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
426 |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
427 if (jvmDebugger != null) { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
428 attach(jvmDebugger); |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
429 } else if (pidText != null) { |
0 | 430 attach(pidText); |
431 } else if (execPath != null) { | |
432 attach(execPath, coreFilename); | |
433 } | |
434 } | |
435 | |
436 // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog | |
437 private void showAttachDialog() { | |
438 // FIXME: create filtered text field which only accepts numbers | |
439 setMenuItemsEnabled(attachMenuItems, false); | |
440 final JInternalFrame attachDialog = new JInternalFrame("Attach to HotSpot process"); | |
441 attachDialog.getContentPane().setLayout(new BorderLayout()); | |
442 | |
443 JPanel panel = new JPanel(); | |
444 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); | |
445 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
446 attachDialog.setBackground(panel.getBackground()); | |
447 | |
448 panel.add(new JLabel("Enter process ID:")); | |
449 final JTextField pidTextField = new JTextField(10); | |
450 ActionListener attacher = new ActionListener() { | |
451 public void actionPerformed(ActionEvent e) { | |
452 attachDialog.setVisible(false); | |
453 desktop.remove(attachDialog); | |
454 workerThread.invokeLater(new Runnable() { | |
455 public void run() { | |
456 attach(pidTextField.getText()); | |
457 } | |
458 }); | |
459 } | |
460 }; | |
461 | |
462 pidTextField.addActionListener(attacher); | |
463 panel.add(pidTextField); | |
464 attachDialog.getContentPane().add(panel, BorderLayout.NORTH); | |
465 | |
466 Box vbox = Box.createVerticalBox(); | |
467 panel = new JPanel(); | |
468 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); | |
469 panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); | |
470 JTextArea ta = new JTextArea( | |
471 "Enter the process ID of a currently-running HotSpot process. On " + | |
472 "Solaris and most Unix operating systems, this can be determined by " + | |
473 "typing \"ps -u <your username> | grep java\"; the process ID is the " + | |
474 "first number which appears on the resulting line. On Windows, the " + | |
475 "process ID is present in the Task Manager, which can be brought up " + | |
476 "while logged on to the desktop by pressing Ctrl-Alt-Delete."); | |
477 ta.setLineWrap(true); | |
478 ta.setWrapStyleWord(true); | |
479 ta.setEditable(false); | |
480 ta.setBackground(panel.getBackground()); | |
481 panel.add(ta); | |
482 vbox.add(panel); | |
483 | |
484 Box hbox = Box.createHorizontalBox(); | |
485 hbox.add(Box.createGlue()); | |
486 JButton button = new JButton("OK"); | |
487 button.addActionListener(attacher); | |
488 hbox.add(button); | |
489 hbox.add(Box.createHorizontalStrut(20)); | |
490 button = new JButton("Cancel"); | |
491 button.addActionListener(new ActionListener() { | |
492 public void actionPerformed(ActionEvent e) { | |
493 attachDialog.setVisible(false); | |
494 desktop.remove(attachDialog); | |
495 setMenuItemsEnabled(attachMenuItems, true); | |
496 } | |
497 }); | |
498 hbox.add(button); | |
499 hbox.add(Box.createGlue()); | |
500 panel = new JPanel(); | |
501 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
502 panel.add(hbox); | |
503 vbox.add(panel); | |
504 | |
505 attachDialog.getContentPane().add(vbox, BorderLayout.SOUTH); | |
506 | |
507 desktop.add(attachDialog); | |
508 attachDialog.setSize(400, 300); | |
509 GraphicsUtilities.centerInContainer(attachDialog); | |
510 attachDialog.show(); | |
511 pidTextField.requestFocus(); | |
512 } | |
513 | |
514 // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog | |
515 private void showOpenCoreFileDialog() { | |
516 setMenuItemsEnabled(attachMenuItems, false); | |
517 final JInternalFrame dialog = new JInternalFrame("Open Core File"); | |
518 dialog.getContentPane().setLayout(new BorderLayout()); | |
519 | |
520 JPanel panel = new JPanel(); | |
521 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); | |
522 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
523 dialog.setBackground(panel.getBackground()); | |
524 | |
525 Box hbox = Box.createHorizontalBox(); | |
526 Box vbox = Box.createVerticalBox(); | |
527 vbox.add(new JLabel("Path to core file:")); | |
528 vbox.add(new JLabel("Path to Java executable:")); | |
529 hbox.add(vbox); | |
530 | |
531 vbox = Box.createVerticalBox(); | |
532 final JTextField corePathField = new JTextField(40); | |
533 final JTextField execPathField = new JTextField(40); | |
534 vbox.add(corePathField); | |
535 vbox.add(execPathField); | |
536 hbox.add(vbox); | |
537 | |
538 final JButton browseCorePath = new JButton("Browse .."); | |
539 final JButton browseExecPath = new JButton("Browse .."); | |
540 browseCorePath.addActionListener(new ActionListener() { | |
541 public void actionPerformed(ActionEvent e) { | |
542 JFileChooser fileChooser = new JFileChooser(new File(".")); | |
543 int retVal = fileChooser.showOpenDialog(dialog); | |
544 if (retVal == JFileChooser.APPROVE_OPTION) { | |
545 corePathField.setText(fileChooser.getSelectedFile().getPath()); | |
546 } | |
547 } | |
548 }); | |
549 browseExecPath.addActionListener(new ActionListener() { | |
550 public void actionPerformed(ActionEvent e) { | |
551 JFileChooser fileChooser = new JFileChooser(new File(".")); | |
552 int retVal = fileChooser.showOpenDialog(dialog); | |
553 if (retVal == JFileChooser.APPROVE_OPTION) { | |
554 execPathField.setText(fileChooser.getSelectedFile().getPath()); | |
555 } | |
556 } | |
557 }); | |
558 vbox = Box.createVerticalBox(); | |
559 vbox.add(browseCorePath); | |
560 vbox.add(browseExecPath); | |
561 hbox.add(vbox); | |
562 | |
563 panel.add(hbox); | |
564 dialog.getContentPane().add(panel, BorderLayout.NORTH); | |
565 | |
566 ActionListener attacher = new ActionListener() { | |
567 public void actionPerformed(ActionEvent e) { | |
568 dialog.setVisible(false); | |
569 desktop.remove(dialog); | |
570 workerThread.invokeLater(new Runnable() { | |
571 public void run() { | |
572 attach(execPathField.getText(), corePathField.getText()); | |
573 } | |
574 }); | |
575 } | |
576 }; | |
577 corePathField.addActionListener(attacher); | |
578 execPathField.addActionListener(attacher); | |
579 | |
580 vbox = Box.createVerticalBox(); | |
581 panel = new JPanel(); | |
582 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); | |
583 panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); | |
584 JTextArea ta = new JTextArea( | |
585 "Enter the full path names to the core file from a HotSpot process " + | |
586 "and the Java executable from which it came. The latter is typically " + | |
587 "located in the JDK/JRE directory under the directory " + | |
588 "jre/bin/<arch>/native_threads."); | |
589 ta.setLineWrap(true); | |
590 ta.setWrapStyleWord(true); | |
591 ta.setEditable(false); | |
592 ta.setBackground(panel.getBackground()); | |
593 panel.add(ta); | |
594 vbox.add(panel); | |
595 | |
596 hbox = Box.createHorizontalBox(); | |
597 hbox.add(Box.createGlue()); | |
598 JButton button = new JButton("OK"); | |
599 button.addActionListener(attacher); | |
600 hbox.add(button); | |
601 hbox.add(Box.createHorizontalStrut(20)); | |
602 button = new JButton("Cancel"); | |
603 button.addActionListener(new ActionListener() { | |
604 public void actionPerformed(ActionEvent e) { | |
605 dialog.setVisible(false); | |
606 desktop.remove(dialog); | |
607 setMenuItemsEnabled(attachMenuItems, true); | |
608 } | |
609 }); | |
610 hbox.add(button); | |
611 hbox.add(Box.createGlue()); | |
612 panel = new JPanel(); | |
613 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
614 panel.add(hbox); | |
615 vbox.add(panel); | |
616 | |
617 dialog.getContentPane().add(vbox, BorderLayout.SOUTH); | |
618 | |
619 desktop.add(dialog); | |
620 dialog.setSize(500, 300); | |
621 GraphicsUtilities.centerInContainer(dialog); | |
622 dialog.show(); | |
623 corePathField.requestFocus(); | |
624 } | |
625 | |
626 // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog | |
627 private void showConnectDialog() { | |
628 // FIXME: create filtered text field which only accepts numbers | |
629 setMenuItemsEnabled(attachMenuItems, false); | |
630 final JInternalFrame dialog = new JInternalFrame("Connect to HotSpot Debug Server"); | |
631 dialog.getContentPane().setLayout(new BorderLayout()); | |
632 | |
633 JPanel panel = new JPanel(); | |
634 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); | |
635 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
636 dialog.setBackground(panel.getBackground()); | |
637 | |
638 panel.add(new JLabel("Enter machine name:")); | |
639 final JTextField pidTextField = new JTextField(40); | |
640 ActionListener attacher = new ActionListener() { | |
641 public void actionPerformed(ActionEvent e) { | |
642 dialog.setVisible(false); | |
643 desktop.remove(dialog); | |
644 workerThread.invokeLater(new Runnable() { | |
645 public void run() { | |
646 connect(pidTextField.getText()); | |
647 } | |
648 }); | |
649 } | |
650 }; | |
651 | |
652 pidTextField.addActionListener(attacher); | |
653 panel.add(pidTextField); | |
654 dialog.getContentPane().add(panel, BorderLayout.NORTH); | |
655 | |
656 Box vbox = Box.createVerticalBox(); | |
657 panel = new JPanel(); | |
658 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); | |
659 panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); | |
660 JTextArea ta = new JTextArea( | |
661 "Enter the name of a machine on which the HotSpot \"Debug Server\" is " + | |
662 "running and is attached to a process or core file."); | |
663 ta.setLineWrap(true); | |
664 ta.setWrapStyleWord(true); | |
665 ta.setEditable(false); | |
666 ta.setBackground(panel.getBackground()); | |
667 panel.add(ta); | |
668 vbox.add(panel); | |
669 | |
670 Box hbox = Box.createHorizontalBox(); | |
671 hbox.add(Box.createGlue()); | |
672 JButton button = new JButton("OK"); | |
673 button.addActionListener(attacher); | |
674 hbox.add(button); | |
675 hbox.add(Box.createHorizontalStrut(20)); | |
676 button = new JButton("Cancel"); | |
677 button.addActionListener(new ActionListener() { | |
678 public void actionPerformed(ActionEvent e) { | |
679 dialog.setVisible(false); | |
680 desktop.remove(dialog); | |
681 setMenuItemsEnabled(attachMenuItems, true); | |
682 } | |
683 }); | |
684 hbox.add(button); | |
685 hbox.add(Box.createGlue()); | |
686 panel = new JPanel(); | |
687 panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); | |
688 panel.add(hbox); | |
689 vbox.add(panel); | |
690 | |
691 dialog.getContentPane().add(vbox, BorderLayout.SOUTH); | |
692 | |
693 desktop.add(dialog); | |
694 dialog.setSize(400, 300); | |
695 GraphicsUtilities.centerInContainer(dialog); | |
696 dialog.show(); | |
697 pidTextField.requestFocus(); | |
698 } | |
699 | |
700 public void showThreadOopInspector(JavaThread thread) { | |
701 showInspector(new OopTreeNodeAdapter(thread.getThreadObj(), null)); | |
702 } | |
703 | |
704 public void showInspector(SimpleTreeNode adapter) { | |
705 showPanel("Inspector", new Inspector(adapter), 1.0f, 0.65f); | |
706 } | |
707 | |
708 public void showLiveness(Oop oop, LivenessPathList liveness) { | |
709 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
710 PrintStream tty = new PrintStream(bos); | |
711 int numPaths = liveness.size(); | |
712 for (int i = 0; i < numPaths; i++) { | |
713 tty.println("Path " + (i + 1) + " of " + numPaths + ":"); | |
714 liveness.get(i).printOn(tty); | |
715 } | |
716 JTextArea ta = new JTextArea(bos.toString()); | |
717 ta.setLineWrap(true); | |
718 ta.setWrapStyleWord(true); | |
719 ta.setEditable(false); | |
720 | |
721 JPanel panel = new JPanel(); | |
722 panel.setLayout(new BorderLayout()); | |
723 | |
724 JScrollPane scroller = new JScrollPane(); | |
725 scroller.getViewport().add(ta); | |
726 | |
727 panel.add(scroller, BorderLayout.CENTER); | |
728 | |
729 bos = new ByteArrayOutputStream(); | |
730 tty = new PrintStream(bos); | |
731 tty.print("Liveness result for "); | |
732 Oop.printOopValueOn(oop, tty); | |
733 | |
734 JInternalFrame frame = new JInternalFrame(bos.toString()); | |
735 frame.setResizable(true); | |
736 frame.setClosable(true); | |
737 frame.setIconifiable(true); | |
738 frame.getContentPane().setLayout(new BorderLayout()); | |
739 frame.getContentPane().add(panel, BorderLayout.CENTER); | |
740 frame.pack(); | |
741 desktop.add(frame); | |
742 GraphicsUtilities.reshapeToAspectRatio(frame, 0.5f / 0.2f, 0.5f, frame.getParent().getSize()); | |
743 frame.show(); | |
744 } | |
745 | |
746 private void fireComputeReversePtrs() { | |
747 // Possible this might have been computed elsewhere | |
748 if (VM.getVM().getRevPtrs() != null) { | |
749 computeRevPtrsMenuItem.setEnabled(false); | |
750 return; | |
751 } | |
752 | |
753 workerThread.invokeLater(new Runnable() { | |
754 public void run() { | |
755 HeapProgress progress = new HeapProgress("Reverse Pointers Analysis"); | |
756 try { | |
757 ReversePtrsAnalysis analysis = new ReversePtrsAnalysis(); | |
758 analysis.setHeapProgressThunk(progress); | |
759 analysis.run(); | |
760 computeRevPtrsMenuItem.setEnabled(false); | |
761 } catch (OutOfMemoryError e) { | |
762 final String errMsg = formatMessage(e.toString(), 80); | |
763 SwingUtilities.invokeLater(new Runnable() { | |
764 public void run() { | |
765 JOptionPane.showInternalMessageDialog(desktop, | |
766 "Error computing reverse pointers:" + errMsg, | |
767 "Error", | |
768 JOptionPane.WARNING_MESSAGE); | |
769 } | |
770 }); | |
771 } finally { | |
772 // make sure the progress bar goes away | |
773 progress.heapIterationComplete(); | |
774 } | |
775 } | |
776 }); | |
777 } | |
778 | |
779 // Simple struct containing signal information | |
780 class SignalInfo { | |
781 public int sigNum; | |
782 public String sigName; | |
783 } | |
784 | |
785 // Need to have mutable vframe as well as visible memory panel | |
786 abstract class StackWalker implements Runnable { | |
787 protected JavaVFrame vf; | |
788 protected AnnotatedMemoryPanel annoPanel; | |
789 | |
790 StackWalker(JavaVFrame vf, AnnotatedMemoryPanel annoPanel) { | |
791 this.vf = vf; | |
792 this.annoPanel = annoPanel; | |
793 } | |
794 } | |
795 | |
796 public void showThreadStackMemory(final JavaThread thread) { | |
797 // dumpStack(thread); | |
798 JavaVFrame vframe = getLastJavaVFrame(thread); | |
799 if (vframe == null) { | |
800 JOptionPane.showInternalMessageDialog(desktop, | |
801 "Thread \"" + thread.getThreadName() + | |
802 "\" has no Java frames on its stack", | |
803 "Show Stack Memory", | |
804 JOptionPane.INFORMATION_MESSAGE); | |
805 return; | |
806 } | |
807 | |
808 JInternalFrame stackFrame = new JInternalFrame("Stack Memory for " + thread.getThreadName()); | |
809 stackFrame.getContentPane().setLayout(new BorderLayout()); | |
810 stackFrame.setResizable(true); | |
811 stackFrame.setClosable(true); | |
812 stackFrame.setIconifiable(true); | |
813 final long addressSize = agent.getTypeDataBase().getAddressSize(); | |
814 boolean is64Bit = (addressSize == 8); | |
815 // This is somewhat of a hack to guess a thread's stack limits since the | |
816 // JavaThread doesn't support this functionality. However it is nice in that | |
817 // it locks us into the active region of the thread's stack and not its | |
818 // theoretical limits. | |
819 // | |
820 sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess(); | |
821 Address sp = tmpFrame.getSP(); | |
822 Address starting = sp; | |
823 Address maxSP = starting; | |
824 Address minSP = starting; | |
825 RegisterMap tmpMap = thread.newRegisterMap(false); | |
826 while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) { | |
827 tmpFrame = tmpFrame.sender(tmpMap); | |
828 if (tmpFrame != null) { | |
829 sp = tmpFrame.getSP(); | |
830 if (sp != null) { | |
831 maxSP = AddressOps.max(maxSP, sp); | |
832 minSP = AddressOps.min(minSP, sp); | |
833 } | |
834 } | |
835 | |
836 } | |
837 // It is useful to be able to see say +/- 8K on the current stack range | |
838 AnnotatedMemoryPanel annoMemPanel = new AnnotatedMemoryPanel(agent.getDebugger(), is64Bit, starting, | |
839 minSP.addOffsetTo(-8192), | |
840 maxSP.addOffsetTo( 8192)); | |
841 | |
842 stackFrame.getContentPane().add(annoMemPanel, BorderLayout.CENTER); | |
843 desktop.add(stackFrame); | |
844 GraphicsUtilities.reshapeToAspectRatio(stackFrame, 4.0f / 3.0f, 0.85f, stackFrame.getParent().getSize()); | |
845 stackFrame.show(); | |
846 | |
847 // Stackmap computation for interpreted frames is expensive; do | |
848 // all stackwalking work in another thread for better GUI | |
849 // responsiveness | |
850 workerThread.invokeLater(new StackWalker(vframe, annoMemPanel) { | |
851 public void run() { | |
852 Address startAddr = null; | |
853 | |
854 // As this is a debugger, we want to provide potential crash | |
855 // information to the user, i.e., by marking signal handler frames | |
856 // on the stack. Since this system is currently targeted at | |
857 // annotating the Java frames (interpreted or compiled) on the | |
858 // stack and not, for example, "external" frames (note the current | |
859 // absence of a PC-to-symbol lookup mechanism at the Debugger | |
860 // level), we want to mark any Java frames which were interrupted | |
861 // by a signal. We do this by making two passes over the stack, | |
862 // one which finds signal handler frames and puts the parent | |
863 // frames in a table and one which finds Java frames and if they | |
864 // are in the table indicates that they were interrupted by a signal. | |
865 | |
866 Map interruptedFrameMap = new HashMap(); | |
867 { | |
868 sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess(); | |
869 RegisterMap tmpMap = thread.newRegisterMap(false); | |
870 while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) { | |
871 if (tmpFrame.isSignalHandlerFrameDbg()) { | |
872 // Add some information to the map that we can extract later | |
873 sun.jvm.hotspot.runtime.Frame interruptedFrame = tmpFrame.sender(tmpMap); | |
874 SignalInfo info = new SignalInfo(); | |
875 info.sigNum = tmpFrame.getSignalNumberDbg(); | |
876 info.sigName = tmpFrame.getSignalNameDbg(); | |
877 interruptedFrameMap.put(interruptedFrame, info); | |
878 } | |
879 tmpFrame = tmpFrame.sender(tmpMap); | |
880 } | |
881 } | |
882 | |
883 while (vf != null) { | |
884 String anno = null; | |
885 JavaVFrame curVFrame = vf; | |
886 sun.jvm.hotspot.runtime.Frame curFrame = curVFrame.getFrame(); | |
887 Method interpreterFrameMethod = null; | |
888 | |
889 if (curVFrame.isInterpretedFrame()) { | |
890 anno = "Interpreted frame"; | |
891 } else { | |
892 anno = "Compiled frame"; | |
893 if (curVFrame.isDeoptimized()) { | |
894 anno += " (deoptimized)"; | |
895 } | |
896 } | |
897 if (curVFrame.mayBeImpreciseDbg()) { | |
898 anno += "; information may be imprecise"; | |
899 } | |
900 | |
901 if (curVFrame.isInterpretedFrame()) { | |
902 // Find the codelet | |
903 InterpreterCodelet codelet = VM.getVM().getInterpreter().getCodeletContaining(curFrame.getPC()); | |
904 String description = null; | |
905 if (codelet != null) { | |
906 description = codelet.getDescription(); | |
907 } | |
908 if (description == null) { | |
909 anno += "\n(Unknown interpreter codelet)"; | |
910 } else { | |
911 anno += "\nExecuting in codelet \"" + description + "\" at PC = " + curFrame.getPC(); | |
912 } | |
913 } else if (curVFrame.isCompiledFrame()) { | |
914 anno += "\nExecuting at PC = " + curFrame.getPC(); | |
915 } | |
916 | |
917 if (startAddr == null) { | |
918 startAddr = curFrame.getSP(); | |
919 } | |
920 | |
921 // FIXME: some compiled frames with empty oop map sets have been | |
922 // found (for example, Vector's inner Enumeration class, method | |
923 // "hasMoreElements"). Not sure yet why these cases are showing | |
924 // up -- should be possible (though unlikely) for safepoint code | |
925 // to patch the return instruction of these methods and then | |
926 // later attempt to get an oop map for that instruction. For | |
927 // now, we warn if we find such a method. | |
928 boolean shouldSkipOopMaps = false; | |
929 if (curVFrame.isCompiledFrame()) { | |
930 CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC()); | |
931 OopMapSet maps = cb.getOopMaps(); | |
932 if ((maps == null) || (maps.getSize() == 0)) { | |
933 shouldSkipOopMaps = true; | |
934 } | |
935 } | |
936 | |
937 // Add signal information to annotation if necessary | |
938 SignalInfo sigInfo = (SignalInfo) interruptedFrameMap.get(curFrame); | |
939 if (sigInfo != null) { | |
940 // This frame took a signal and we need to report it. | |
941 anno = (anno + "\n*** INTERRUPTED BY SIGNAL " + Integer.toString(sigInfo.sigNum) + | |
942 " (" + sigInfo.sigName + ")"); | |
943 } | |
944 | |
945 JavaVFrame nextVFrame = curVFrame; | |
946 sun.jvm.hotspot.runtime.Frame nextFrame = curFrame; | |
947 do { | |
948 curVFrame = nextVFrame; | |
949 curFrame = nextFrame; | |
950 | |
951 try { | |
952 Method method = curVFrame.getMethod(); | |
953 if (interpreterFrameMethod == null && curVFrame.isInterpretedFrame()) { | |
954 interpreterFrameMethod = method; | |
955 } | |
956 int bci = curVFrame.getBCI(); | |
957 String lineNumberAnno = ""; | |
958 if (method.hasLineNumberTable()) { | |
959 if ((bci == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) || | |
960 (bci >= 0 && bci < method.getCodeSize())) { | |
961 lineNumberAnno = ", line " + method.getLineNumberFromBCI(bci); | |
962 } else { | |
963 lineNumberAnno = " (INVALID BCI)"; | |
964 } | |
965 } | |
966 anno += "\n" + method.getMethodHolder().getName().asString() + "." + | |
967 method.getName().asString() + method.getSignature().asString() + | |
968 "\n@bci " + bci + lineNumberAnno; | |
969 } catch (Exception e) { | |
970 anno += "\n(ERROR while iterating vframes for frame " + curFrame + ")"; | |
971 } | |
972 | |
973 nextVFrame = curVFrame.javaSender(); | |
974 if (nextVFrame != null) { | |
975 nextFrame = nextVFrame.getFrame(); | |
976 } | |
977 } while (nextVFrame != null && nextFrame.equals(curFrame)); | |
978 | |
979 if (shouldSkipOopMaps) { | |
980 anno = anno + "\nNOTE: null or empty OopMapSet found for this CodeBlob"; | |
981 } | |
982 | |
983 if (curFrame.getFP() != null) { | |
984 annoPanel.addAnnotation(new Annotation(curFrame.getSP(), | |
985 curFrame.getFP(), | |
986 anno)); | |
987 } else { | |
988 if (VM.getVM().getCPU().equals("x86") || VM.getVM().getCPU().equals("amd64")) { | |
989 // For C2, which has null frame pointers on x86/amd64 | |
990 CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC()); | |
991 Address sp = curFrame.getSP(); | |
992 if (Assert.ASSERTS_ENABLED) { | |
993 Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size"); | |
994 } | |
995 annoPanel.addAnnotation(new Annotation(sp, | |
996 sp.addOffsetTo(cb.getFrameSize()), | |
997 anno)); | |
998 } else { | |
999 Assert.that(VM.getVM().getCPU().equals("ia64"), "only ia64 should reach here"); | |
1000 } | |
1001 } | |
1002 | |
1003 // Add interpreter frame annotations | |
1004 if (curFrame.isInterpretedFrame()) { | |
1005 annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameExpressionStack(), | |
1006 curFrame.addressOfInterpreterFrameTOS(), | |
1007 "Interpreter expression stack")); | |
1385 | 1008 Address monBegin = curFrame.interpreterFrameMonitorBegin().address(); |
1009 Address monEnd = curFrame.interpreterFrameMonitorEnd().address(); | |
1010 if (!monBegin.equals(monEnd)) { | |
1011 annoPanel.addAnnotation(new Annotation(monBegin, monEnd, | |
1012 "BasicObjectLocks")); | |
1013 } | |
0 | 1014 if (interpreterFrameMethod != null) { |
1015 // The offset is just to get the right stack slots highlighted in the output | |
1016 int offset = 1; | |
1017 annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameLocal(offset), | |
1018 curFrame.addressOfInterpreterFrameLocal((int) interpreterFrameMethod.getMaxLocals() + offset), | |
1019 "Interpreter locals area for frame with SP = " + curFrame.getSP())); | |
1020 } | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3908
diff
changeset
|
1021 String methodAnno = "Interpreter frame Method*"; |
0 | 1022 if (interpreterFrameMethod == null) { |
1023 methodAnno += " (BAD OOP)"; | |
1024 } | |
1025 Address a = curFrame.addressOfInterpreterFrameMethod(); | |
1026 annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), methodAnno)); | |
1027 a = curFrame.addressOfInterpreterFrameCPCache(); | |
1028 annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), "Interpreter constant pool cache")); | |
1029 } | |
1030 | |
1031 RegisterMap rm = (RegisterMap) vf.getRegisterMap().clone(); | |
1032 if (!shouldSkipOopMaps) { | |
1033 try { | |
1034 curFrame.oopsDo(new AddressVisitor() { | |
1035 public void visitAddress(Address addr) { | |
1036 if (Assert.ASSERTS_ENABLED) { | |
1037 Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, | |
1038 "Address " + addr + "should have been aligned"); | |
1039 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1040 OopHandle handle = addr.getOopHandleAt(0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1041 addAnnotation(addr, handle); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1042 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1043 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1044 public void visitCompOopAddress(Address addr) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1045 if (Assert.ASSERTS_ENABLED) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1046 Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1047 "Address " + addr + "should have been aligned"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1048 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1049 OopHandle handle = addr.getCompOopHandleAt(0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1050 addAnnotation(addr, handle); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1051 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1052 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1053 public void addAnnotation(Address addr, OopHandle handle) { |
0 | 1054 // Check contents |
1055 String anno = "null oop"; | |
1056 if (handle != null) { | |
1057 // Find location | |
1058 CollectedHeap collHeap = VM.getVM().getUniverse().heap(); | |
1059 boolean bad = true; | |
1060 anno = "BAD OOP"; | |
1061 if (collHeap instanceof GenCollectedHeap) { | |
1062 GenCollectedHeap heap = (GenCollectedHeap) collHeap; | |
1063 for (int i = 0; i < heap.nGens(); i++) { | |
1064 if (heap.getGen(i).isIn(handle)) { | |
1065 if (i == 0) { | |
1066 anno = "NewGen "; | |
1067 } else if (i == 1) { | |
1068 anno = "OldGen "; | |
1069 } else { | |
1070 anno = "Gen " + i + " "; | |
1071 } | |
1072 bad = false; | |
1073 break; | |
1074 } | |
1075 } | |
1076 | |
1077 } else if (collHeap instanceof ParallelScavengeHeap) { | |
1078 ParallelScavengeHeap heap = (ParallelScavengeHeap) collHeap; | |
1079 if (heap.youngGen().isIn(handle)) { | |
1080 anno = "PSYoungGen "; | |
1081 bad = false; | |
1082 } else if (heap.oldGen().isIn(handle)) { | |
1083 anno = "PSOldGen "; | |
1084 bad = false; | |
1085 } | |
1086 } else { | |
1087 // Optimistically assume the oop isn't bad | |
1088 anno = "[Unknown generation] "; | |
1089 bad = false; | |
1090 } | |
1091 | |
1092 if (!bad) { | |
1093 try { | |
1094 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
1095 if (oop instanceof Instance) { | |
1096 // Java-level objects always have workable names | |
1097 anno = anno + oop.getKlass().getName().asString(); | |
1098 } else { | |
1099 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1100 Oop.printOopValueOn(oop, new PrintStream(bos)); | |
1101 anno = anno + bos.toString(); | |
1102 } | |
1103 } | |
1104 catch (AddressException e) { | |
1105 anno += "CORRUPT OOP"; | |
1106 } | |
1107 catch (NullPointerException e) { | |
1108 anno += "CORRUPT OOP (null pointer)"; | |
1109 } | |
1110 } | |
1111 } | |
1112 | |
1113 annoPanel.addAnnotation(new Annotation(addr, addr.addOffsetTo(addressSize), anno)); | |
1114 } | |
1115 }, rm); | |
1116 } catch (Exception e) { | |
1117 System.err.println("Error while performing oopsDo for frame " + curFrame); | |
1118 e.printStackTrace(); | |
1119 } | |
1120 } | |
1121 | |
1122 vf = nextVFrame; | |
1123 } | |
1124 | |
1125 // This used to paint as we walked the frames. This caused the display to be refreshed | |
1126 // enough to be annoying on remote displays. It also would cause the annotations to | |
1127 // be displayed in varying order which caused some annotations to overwrite others | |
1128 // depending on the races between painting and adding annotations. This latter problem | |
1129 // still exists to some degree but moving this code here definitely seems to reduce it | |
1130 annoPanel.makeVisible(startAddr); | |
1131 annoPanel.repaint(); | |
1132 } | |
1133 }); | |
1134 } | |
1135 | |
11054
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1136 // Attach to existing JVMDebugger, which should be already attached to a core/process. |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1137 private void attach(JVMDebugger d) { |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1138 attached = true; |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1139 showThreadsDialog(); |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1140 } |
38ea2efa32a7
8010278: SA: provide mechanism for using an alternative SA debugger back-end.
kevinw
parents:
6725
diff
changeset
|
1141 |
0 | 1142 /** NOTE we are in a different thread here than either the main |
1143 thread or the Swing/AWT event handler thread, so we must be very | |
1144 careful when creating or removing widgets */ | |
1145 private void attach(String pidText) { | |
1146 try { | |
1147 this.pidText = pidText; | |
1148 pid = Integer.parseInt(pidText); | |
1149 } | |
1150 catch (NumberFormatException e) { | |
1151 SwingUtilities.invokeLater(new Runnable() { | |
1152 public void run() { | |
1153 setMenuItemsEnabled(attachMenuItems, true); | |
1154 JOptionPane.showInternalMessageDialog(desktop, | |
1155 "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.", | |
1156 "Parse error", | |
1157 JOptionPane.WARNING_MESSAGE); | |
1158 } | |
1159 }); | |
1160 return; | |
1161 } | |
1162 | |
1163 // Try to attach to this process | |
1164 Runnable remover = new Runnable() { | |
1165 public void run() { | |
1166 attachWaitDialog.setVisible(false); | |
1167 desktop.remove(attachWaitDialog); | |
1168 attachWaitDialog = null; | |
1169 } | |
1170 }; | |
1171 | |
1172 try { | |
1173 SwingUtilities.invokeLater(new Runnable() { | |
1174 public void run() { | |
1175 JOptionPane pane = new JOptionPane("Attaching to process " + pid + ", please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1176 pane.setOptions(new Object[] {}); | |
1177 attachWaitDialog = pane.createInternalFrame(desktop, "Attaching to Process"); | |
1178 attachWaitDialog.show(); | |
1179 } | |
1180 }); | |
1181 | |
1182 // FIXME: display exec'd debugger's output messages during this | |
1183 // lengthy call | |
1184 agent.attach(pid); | |
1185 if (agent.getDebugger().hasConsole()) { | |
1186 showDbgConsoleMenuItem.setEnabled(true); | |
1187 } | |
1188 attached = true; | |
1189 SwingUtilities.invokeLater(remover); | |
1190 } | |
1191 catch (DebuggerException e) { | |
1192 SwingUtilities.invokeLater(remover); | |
1193 final String errMsg = formatMessage(e.getMessage(), 80); | |
1194 SwingUtilities.invokeLater(new Runnable() { | |
1195 public void run() { | |
1196 setMenuItemsEnabled(attachMenuItems, true); | |
1197 JOptionPane.showInternalMessageDialog(desktop, | |
1198 "Unable to connect to process ID " + pid + ":\n\n" + errMsg, | |
1199 "Unable to Connect", | |
1200 JOptionPane.WARNING_MESSAGE); | |
1201 } | |
1202 }); | |
1203 agent.detach(); | |
1204 return; | |
1205 } | |
1206 | |
1207 // OK, the VM should be available. Create the Threads dialog. | |
1208 showThreadsDialog(); | |
1209 } | |
1210 | |
1211 /** NOTE we are in a different thread here than either the main | |
1212 thread or the Swing/AWT event handler thread, so we must be very | |
1213 careful when creating or removing widgets */ | |
1214 private void attach(final String executablePath, final String corePath) { | |
1215 // Try to open this core file | |
1216 Runnable remover = new Runnable() { | |
1217 public void run() { | |
1218 attachWaitDialog.setVisible(false); | |
1219 desktop.remove(attachWaitDialog); | |
1220 attachWaitDialog = null; | |
1221 } | |
1222 }; | |
1223 | |
1224 try { | |
1225 SwingUtilities.invokeLater(new Runnable() { | |
1226 public void run() { | |
1227 JOptionPane pane = new JOptionPane("Opening core file, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1228 pane.setOptions(new Object[] {}); | |
1229 attachWaitDialog = pane.createInternalFrame(desktop, "Opening Core File"); | |
1230 attachWaitDialog.show(); | |
1231 } | |
1232 }); | |
1233 | |
1234 // FIXME: display exec'd debugger's output messages during this | |
1235 // lengthy call | |
1236 agent.attach(executablePath, corePath); | |
1237 if (agent.getDebugger().hasConsole()) { | |
1238 showDbgConsoleMenuItem.setEnabled(true); | |
1239 } | |
1240 attached = true; | |
1241 SwingUtilities.invokeLater(remover); | |
1242 } | |
1243 catch (DebuggerException e) { | |
1244 SwingUtilities.invokeLater(remover); | |
1245 final String errMsg = formatMessage(e.getMessage(), 80); | |
1246 SwingUtilities.invokeLater(new Runnable() { | |
1247 public void run() { | |
1248 setMenuItemsEnabled(attachMenuItems, true); | |
1249 JOptionPane.showInternalMessageDialog(desktop, | |
1250 "Unable to open core file\n" + corePath + ":\n\n" + errMsg, | |
1251 "Unable to Open Core File", | |
1252 JOptionPane.WARNING_MESSAGE); | |
1253 } | |
1254 }); | |
1255 agent.detach(); | |
1256 return; | |
1257 } | |
1258 | |
1259 // OK, the VM should be available. Create the Threads dialog. | |
1260 showThreadsDialog(); | |
1261 } | |
1262 | |
1263 /** NOTE we are in a different thread here than either the main | |
1264 thread or the Swing/AWT event handler thread, so we must be very | |
1265 careful when creating or removing widgets */ | |
1266 private void connect(final String remoteMachineName) { | |
1267 // Try to open this core file | |
1268 Runnable remover = new Runnable() { | |
1269 public void run() { | |
1270 attachWaitDialog.setVisible(false); | |
1271 desktop.remove(attachWaitDialog); | |
1272 attachWaitDialog = null; | |
1273 } | |
1274 }; | |
1275 | |
1276 try { | |
1277 SwingUtilities.invokeLater(new Runnable() { | |
1278 public void run() { | |
1279 JOptionPane pane = new JOptionPane("Connecting to debug server, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1280 pane.setOptions(new Object[] {}); | |
1281 attachWaitDialog = pane.createInternalFrame(desktop, "Connecting to Debug Server"); | |
1282 attachWaitDialog.show(); | |
1283 } | |
1284 }); | |
1285 | |
1286 agent.attach(remoteMachineName); | |
1287 if (agent.getDebugger().hasConsole()) { | |
1288 showDbgConsoleMenuItem.setEnabled(true); | |
1289 } | |
1290 attached = true; | |
1291 SwingUtilities.invokeLater(remover); | |
1292 } | |
1293 catch (DebuggerException e) { | |
1294 SwingUtilities.invokeLater(remover); | |
1295 final String errMsg = formatMessage(e.getMessage(), 80); | |
1296 SwingUtilities.invokeLater(new Runnable() { | |
1297 public void run() { | |
1298 setMenuItemsEnabled(attachMenuItems, true); | |
1299 JOptionPane.showInternalMessageDialog(desktop, | |
1300 "Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg, | |
1301 "Unable to Connect", | |
1302 JOptionPane.WARNING_MESSAGE); | |
1303 } | |
1304 }); | |
1305 agent.detach(); | |
1306 return; | |
1307 } | |
1308 | |
1309 // OK, the VM should be available. Create the Threads dialog. | |
1310 showThreadsDialog(); | |
1311 } | |
1312 | |
1313 private void detachDebugger() { | |
1314 if (!attached) { | |
1315 return; | |
1316 } | |
1317 agent.detach(); | |
1318 attached = false; | |
1319 } | |
1320 | |
1321 private void detach() { | |
1322 detachDebugger(); | |
1323 attachWaitDialog = null; | |
1324 threadsFrame = null; | |
1325 consoleFrame = null; | |
1326 setMenuItemsEnabled(attachMenuItems, true); | |
1327 setMenuItemsEnabled(detachMenuItems, false); | |
1328 toolsMenu.setEnabled(false); | |
1329 showDbgConsoleMenuItem.setEnabled(false); | |
1330 // FIXME: is this sufficient, or will I have to do anything else | |
1331 // to the components to kill them off? What about WorkerThreads? | |
1332 desktop.removeAll(); | |
1333 desktop.invalidate(); | |
1334 desktop.validate(); | |
1335 desktop.repaint(); | |
1336 } | |
1337 | |
1338 /** NOTE that this is called from another thread than the main or | |
1339 Swing thread and we have to be careful about synchronization */ | |
1340 private void showThreadsDialog() { | |
1341 SwingUtilities.invokeLater(new Runnable() { | |
1342 public void run() { | |
1343 threadsFrame = new JInternalFrame("Java Threads"); | |
1344 threadsFrame.setResizable(true); | |
1345 threadsFrame.setIconifiable(true); | |
1346 JavaThreadsPanel threadsPanel = new JavaThreadsPanel(); | |
1347 threadsPanel.addPanelListener(HSDB.this); | |
1348 threadsFrame.getContentPane().add(threadsPanel); | |
1349 threadsFrame.setSize(500, 300); | |
1350 threadsFrame.pack(); | |
1351 desktop.add(threadsFrame); | |
1352 GraphicsUtilities.moveToInContainer(threadsFrame, 0.75f, 0.25f, 0, 20); | |
1353 threadsFrame.show(); | |
1354 setMenuItemsEnabled(attachMenuItems, false); | |
1355 setMenuItemsEnabled(detachMenuItems, true); | |
1356 toolsMenu.setEnabled(true); | |
1357 VM.registerVMInitializedObserver(new Observer() { | |
1358 public void update(Observable o, Object data) { | |
1359 computeRevPtrsMenuItem.setEnabled(true); | |
1360 } | |
1361 }); | |
1362 } | |
1363 }); | |
1364 } | |
1365 | |
1366 private void showObjectHistogram() { | |
1367 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1368 ObjectHistogramCleanupThunk cleanup = | |
1369 new ObjectHistogramCleanupThunk(histo); | |
1370 doHeapIteration("Object Histogram", | |
1371 "Generating histogram...", | |
1372 histo, | |
1373 cleanup); | |
1374 } | |
1375 | |
1376 class ObjectHistogramCleanupThunk implements CleanupThunk { | |
1377 sun.jvm.hotspot.oops.ObjectHistogram histo; | |
1378 | |
1379 ObjectHistogramCleanupThunk(sun.jvm.hotspot.oops.ObjectHistogram histo) { | |
1380 this.histo = histo; | |
1381 } | |
1382 | |
1383 public void heapIterationComplete() { | |
1384 SwingUtilities.invokeLater(new Runnable() { | |
1385 public void run() { | |
1386 JInternalFrame histoFrame = new JInternalFrame("Object Histogram"); | |
1387 histoFrame.setResizable(true); | |
1388 histoFrame.setClosable(true); | |
1389 histoFrame.setIconifiable(true); | |
1390 histoFrame.getContentPane().setLayout(new BorderLayout()); | |
1391 ObjectHistogramPanel panel = new ObjectHistogramPanel(histo); | |
1392 panel.addPanelListener(HSDB.this); | |
1393 histoFrame.getContentPane().add(panel); | |
1394 desktop.add(histoFrame); | |
1395 GraphicsUtilities.reshapeToAspectRatio(histoFrame, 4.0f / 3.0f, 0.6f, | |
1396 histoFrame.getParent().getSize()); | |
1397 GraphicsUtilities.centerInContainer(histoFrame); | |
1398 histoFrame.show(); | |
1399 } | |
1400 }); | |
1401 } | |
1402 } | |
1403 | |
1404 public void showObjectsOfType(Klass type) { | |
1405 FindObjectByType finder = new FindObjectByType(type); | |
1406 FindObjectByTypeCleanupThunk cleanup = | |
1407 new FindObjectByTypeCleanupThunk(finder); | |
1408 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1409 type.printValueOn(new PrintStream(bos)); | |
1410 String typeName = bos.toString(); | |
1411 doHeapIteration("Show Objects Of Type", | |
1412 "Finding instances of \"" + typeName + "\"", | |
1413 finder, | |
1414 cleanup); | |
1415 } | |
1416 | |
1417 class FindObjectByTypeCleanupThunk implements CleanupThunk { | |
1418 FindObjectByType finder; | |
1419 | |
1420 FindObjectByTypeCleanupThunk(FindObjectByType finder) { | |
1421 this.finder = finder; | |
1422 } | |
1423 | |
1424 public void heapIterationComplete() { | |
1425 SwingUtilities.invokeLater(new Runnable() { | |
1426 public void run() { | |
1427 JInternalFrame finderFrame = new JInternalFrame("Show Objects of Type"); | |
1428 finderFrame.getContentPane().setLayout(new BorderLayout()); | |
1429 finderFrame.setResizable(true); | |
1430 finderFrame.setClosable(true); | |
1431 finderFrame.setIconifiable(true); | |
1432 ObjectListPanel panel = new ObjectListPanel(finder.getResults(), | |
1433 new HeapProgress("Reverse Pointers Analysis")); | |
1434 panel.addPanelListener(HSDB.this); | |
1435 finderFrame.getContentPane().add(panel); | |
1436 desktop.add(finderFrame); | |
1437 GraphicsUtilities.reshapeToAspectRatio(finderFrame, 4.0f / 3.0f, 0.6f, | |
1438 finderFrame.getParent().getSize()); | |
1439 GraphicsUtilities.centerInContainer(finderFrame); | |
1440 finderFrame.show(); | |
1441 } | |
1442 }); | |
1443 } | |
1444 } | |
1445 | |
1446 private void showDebuggerConsole() { | |
1447 if (consoleFrame == null) { | |
1448 consoleFrame = new JInternalFrame("Debugger Console"); | |
1449 consoleFrame.setResizable(true); | |
1450 consoleFrame.setClosable(true); | |
1451 consoleFrame.setIconifiable(true); | |
1452 consoleFrame.getContentPane().setLayout(new BorderLayout()); | |
1453 consoleFrame.getContentPane().add(new DebuggerConsolePanel(agent.getDebugger()), BorderLayout.CENTER); | |
1454 GraphicsUtilities.reshapeToAspectRatio(consoleFrame, 5.0f, 0.9f, desktop.getSize()); | |
1455 } | |
1456 if (consoleFrame.getParent() == null) { | |
1457 desktop.add(consoleFrame); | |
1458 } | |
1459 consoleFrame.setVisible(true); | |
1460 consoleFrame.show(); | |
1461 consoleFrame.getContentPane().getComponent(0).requestFocus(); | |
1462 } | |
1463 | |
1464 private void showConsole() { | |
1465 CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() { | |
1466 public HotSpotAgent getAgent() { | |
1467 return agent; | |
1468 } | |
1469 public boolean isAttached() { | |
1470 return attached; | |
1471 } | |
1472 public void attach(String pid) { | |
1473 attach(pid); | |
1474 } | |
1475 public void attach(String java, String core) { | |
1476 } | |
1477 public void detach() { | |
1478 detachDebugger(); | |
1479 } | |
1480 public void reattach() { | |
1481 if (attached) { | |
1482 detachDebugger(); | |
1483 } | |
1484 if (pidText != null) { | |
1485 attach(pidText); | |
1486 } else { | |
1487 attach(execPath, coreFilename); | |
1488 } | |
1489 } | |
1490 }; | |
1491 | |
1492 showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null))); | |
1493 } | |
1494 | |
1495 private void showFindByQueryPanel() { | |
1496 showPanel("Find Object by Query", new FindByQueryPanel()); | |
1497 } | |
1498 | |
1499 private void showFindPanel() { | |
1500 showPanel("Find Pointer", new FindPanel()); | |
1501 } | |
1502 | |
1503 private void showFindInHeapPanel() { | |
1504 showPanel("Find Address In Heap", new FindInHeapPanel()); | |
1505 } | |
1506 | |
1507 private void showFindInCodeCachePanel() { | |
1508 showPanel("Find Address In Code Cache", new FindInCodeCachePanel()); | |
1509 } | |
1510 | |
1511 private void showHeapParametersPanel() { | |
1512 showPanel("Heap Parameters", new HeapParametersPanel()); | |
1513 } | |
1514 | |
1515 public void showThreadInfo(final JavaThread thread) { | |
1516 showPanel("Info for " + thread.getThreadName(), new ThreadInfoPanel(thread)); | |
1517 } | |
1518 | |
1519 public void showJavaStackTrace(final JavaThread thread) { | |
1520 JavaStackTracePanel jstp = new JavaStackTracePanel(); | |
1521 showPanel("Java stack trace for " + thread.getThreadName(), jstp); | |
1522 jstp.setJavaThread(thread); | |
1523 } | |
1524 | |
1525 private void showDeadlockDetectionPanel() { | |
1526 showPanel("Deadlock Detection", new DeadlockDetectionPanel()); | |
1527 } | |
1528 | |
1529 private void showMonitorCacheDumpPanel() { | |
1530 showPanel("Monitor Cache Dump", new MonitorCacheDumpPanel()); | |
1531 } | |
1532 | |
1533 public void showClassBrowser() { | |
1534 final JInternalFrame progressFrame = new JInternalFrame("Class Browser"); | |
1535 progressFrame.setResizable(true); | |
1536 progressFrame.setClosable(true); | |
1537 progressFrame.setIconifiable(true); | |
1538 progressFrame.getContentPane().setLayout(new BorderLayout()); | |
1539 final ProgressBarPanel bar = new ProgressBarPanel("Generating class list .."); | |
1540 bar.setIndeterminate(true); | |
1541 progressFrame.getContentPane().add(bar, BorderLayout.CENTER); | |
1542 desktop.add(progressFrame); | |
1543 progressFrame.pack(); | |
1544 GraphicsUtilities.centerInContainer(progressFrame); | |
1545 progressFrame.show(); | |
1546 | |
1547 workerThread.invokeLater(new Runnable() { | |
1548 public void run() { | |
1549 HTMLGenerator htmlGen = new HTMLGenerator(); | |
1550 InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses(); | |
1551 final String htmlText = htmlGen.genHTMLForKlassNames(klasses); | |
1552 SwingUtilities.invokeLater(new Runnable() { | |
1553 public void run() { | |
1554 JInternalFrame cbFrame = new JInternalFrame("Class Browser"); | |
1555 cbFrame.getContentPane().setLayout(new BorderLayout()); | |
1556 cbFrame.setResizable(true); | |
1557 cbFrame.setClosable(true); | |
1558 cbFrame.setIconifiable(true); | |
1559 ClassBrowserPanel cbPanel = new ClassBrowserPanel(); | |
1560 cbFrame.getContentPane().add(cbPanel, BorderLayout.CENTER); | |
1561 desktop.remove(progressFrame); | |
1562 desktop.repaint(); | |
1563 desktop.add(cbFrame); | |
1564 GraphicsUtilities.reshapeToAspectRatio(cbFrame, 1.25f, 0.85f, | |
1565 cbFrame.getParent().getSize()); | |
1566 cbFrame.show(); | |
1567 cbPanel.setClassesText(htmlText); | |
1568 } | |
1569 }); | |
1570 } | |
1571 }); | |
1572 } | |
1573 | |
1574 public void showCodeViewer() { | |
1575 showPanel("Code Viewer", new CodeViewerPanel(), 1.25f, 0.85f); | |
1576 } | |
1577 | |
1578 public void showCodeViewer(final Address address) { | |
1579 final CodeViewerPanel panel = new CodeViewerPanel(); | |
1580 showPanel("Code Viewer", panel, 1.25f, 0.85f); | |
1581 SwingUtilities.invokeLater(new Runnable() { | |
1582 public void run() { | |
1583 panel.viewAddress(address); | |
1584 } | |
1585 }); | |
1586 | |
1587 } | |
1588 | |
1589 public void showMemoryViewer() { | |
1590 showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8)); | |
1591 } | |
1592 | |
1593 public void showCommandLineFlags() { | |
1594 showPanel("Command Line Flags", new VMFlagsPanel()); | |
1595 } | |
1596 | |
1597 public void showVMVersion() { | |
1598 showPanel("VM Version Info", new VMVersionInfoPanel()); | |
1599 } | |
1600 | |
1601 public void showSystemProperties() { | |
1602 showPanel("System Properties", new SysPropsPanel()); | |
1603 } | |
1604 | |
1605 private void showPanel(String name, JPanel panel) { | |
1606 showPanel(name, panel, 5.0f / 3.0f, 0.4f); | |
1607 } | |
1608 | |
1609 private void showPanel(String name, JPanel panel, float aspectRatio, float fillRatio) { | |
1610 JInternalFrame frame = new JInternalFrame(name); | |
1611 frame.getContentPane().setLayout(new BorderLayout()); | |
1612 frame.setResizable(true); | |
1613 frame.setClosable(true); | |
1614 frame.setIconifiable(true); | |
1615 frame.setMaximizable(true); | |
1616 frame.getContentPane().add(panel, BorderLayout.CENTER); | |
1617 desktop.add(frame); | |
1618 GraphicsUtilities.reshapeToAspectRatio(frame, aspectRatio, fillRatio, frame.getParent().getSize()); | |
1619 GraphicsUtilities.randomLocation(frame); | |
1620 frame.show(); | |
1621 if (panel instanceof SAPanel) { | |
1622 ((SAPanel)panel).addPanelListener(this); | |
1623 } | |
1624 } | |
1625 | |
1626 //-------------------------------------------------------------------------------- | |
1627 // Framework for heap iteration with progress bar | |
1628 // | |
1629 | |
1630 interface CleanupThunk { | |
1631 public void heapIterationComplete(); | |
1632 } | |
1633 | |
1634 class HeapProgress implements HeapProgressThunk { | |
1635 private JInternalFrame frame; | |
1636 private ProgressBarPanel bar; | |
1637 private String windowTitle; | |
1638 private String progressBarTitle; | |
1639 private CleanupThunk cleanup; | |
1640 | |
1641 HeapProgress(String windowTitle) { | |
1642 this(windowTitle, "Percentage of heap visited", null); | |
1643 } | |
1644 | |
1645 HeapProgress(String windowTitle, String progressBarTitle) { | |
1646 this(windowTitle, progressBarTitle, null); | |
1647 } | |
1648 | |
1649 HeapProgress(String windowTitle, String progressBarTitle, CleanupThunk cleanup) { | |
1650 this.windowTitle = windowTitle; | |
1651 this.progressBarTitle = progressBarTitle; | |
1652 this.cleanup = cleanup; | |
1653 } | |
1654 | |
1655 public void heapIterationFractionUpdate(final double fractionOfHeapVisited) { | |
1656 if (frame == null) { | |
1657 SwingUtilities.invokeLater(new Runnable() { | |
1658 public void run() { | |
1659 frame = new JInternalFrame(windowTitle); | |
1660 frame.setResizable(true); | |
1661 frame.setIconifiable(true); | |
1662 frame.getContentPane().setLayout(new BorderLayout()); | |
1663 bar = new ProgressBarPanel(progressBarTitle); | |
1664 frame.getContentPane().add(bar, BorderLayout.CENTER); | |
1665 desktop.add(frame); | |
1666 frame.pack(); | |
1667 GraphicsUtilities.constrainToSize(frame, frame.getParent().getSize()); | |
1668 GraphicsUtilities.centerInContainer(frame); | |
1669 frame.show(); | |
1670 } | |
1671 }); | |
1672 } | |
1673 | |
1674 SwingUtilities.invokeLater(new Runnable() { | |
1675 public void run() { | |
1676 bar.setValue(fractionOfHeapVisited); | |
1677 } | |
1678 }); | |
1679 } | |
1680 | |
1681 public void heapIterationComplete() { | |
1682 SwingUtilities.invokeLater(new Runnable() { | |
1683 public void run() { | |
1684 desktop.remove(frame); | |
1685 desktop.repaint(); | |
1686 if (VM.getVM().getRevPtrs() != null) { | |
1687 // Ended up computing reverse pointers as a side-effect | |
1688 computeRevPtrsMenuItem.setEnabled(false); | |
1689 } | |
1690 } | |
1691 }); | |
1692 | |
1693 if (cleanup != null) { | |
1694 cleanup.heapIterationComplete(); | |
1695 } | |
1696 } | |
1697 } | |
1698 | |
1699 class VisitHeap implements Runnable { | |
1700 HeapVisitor visitor; | |
1701 | |
1702 VisitHeap(HeapVisitor visitor) { | |
1703 this.visitor = visitor; | |
1704 } | |
1705 | |
1706 public void run() { | |
1707 VM.getVM().getObjectHeap().iterate(visitor); | |
1708 } | |
1709 } | |
1710 | |
1711 private void doHeapIteration(String frameTitle, | |
1712 String progressBarText, | |
1713 HeapVisitor visitor, | |
1714 CleanupThunk cleanup) { | |
1715 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1716 HeapProgress progress = new HeapProgress(frameTitle, | |
1717 progressBarText, | |
1718 cleanup); | |
1719 HeapVisitor progVisitor = new ProgressiveHeapVisitor(visitor, progress); | |
1720 workerThread.invokeLater(new VisitHeap(progVisitor)); | |
1721 } | |
1722 | |
1723 //-------------------------------------------------------------------------------- | |
1724 // Stack trace helper | |
1725 // | |
1726 | |
1727 private static JavaVFrame getLastJavaVFrame(JavaThread cur) { | |
1728 RegisterMap regMap = cur.newRegisterMap(true); | |
1729 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1730 if (f == null) return null; | |
1731 boolean imprecise = true; | |
1732 if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) { | |
1733 System.err.println("Correcting for invalid interpreter frame"); | |
1734 f = f.sender(regMap); | |
1735 imprecise = false; | |
1736 } | |
1737 VFrame vf = VFrame.newVFrame(f, regMap, cur, true, imprecise); | |
1738 if (vf == null) { | |
1739 System.err.println(" (Unable to create vframe for topmost frame guess)"); | |
1740 return null; | |
1741 } | |
1742 if (vf.isJavaFrame()) { | |
1743 return (JavaVFrame) vf; | |
1744 } | |
1745 return (JavaVFrame) vf.javaSender(); | |
1746 } | |
1747 | |
1748 // Internal routine for debugging | |
1749 private static void dumpStack(JavaThread cur) { | |
1750 RegisterMap regMap = cur.newRegisterMap(true); | |
1751 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1752 PrintStream tty = System.err; | |
1753 while (f != null) { | |
1754 tty.print("Found "); | |
1755 if (f.isInterpretedFrame()) { tty.print("interpreted"); } | |
1756 else if (f.isCompiledFrame()) { tty.print("compiled"); } | |
1757 else if (f.isEntryFrame()) { tty.print("entry"); } | |
1758 else if (f.isNativeFrame()) { tty.print("native"); } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
1759 else if (f.isRuntimeFrame()) { tty.print("runtime"); } |
0 | 1760 else { tty.print("external"); } |
1761 tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP()); | |
1762 if (f.isSignalHandlerFrameDbg()) { | |
1763 tty.print(" (SIGNAL HANDLER)"); | |
1764 } | |
1765 tty.println(); | |
1766 | |
1767 if (!f.isFirstFrame()) { | |
1768 f = f.sender(regMap); | |
1769 } else { | |
1770 f = null; | |
1771 } | |
1772 } | |
1773 } | |
1774 | |
1775 //-------------------------------------------------------------------------------- | |
1776 // Component utilities | |
1777 // | |
1778 | |
1779 private static JMenuItem createMenuItem(String name, ActionListener l) { | |
1780 JMenuItem item = new JMenuItem(name); | |
1781 item.addActionListener(l); | |
1782 return item; | |
1783 } | |
1784 | |
1785 /** Punctuates the given string with \n's where necessary to not | |
1786 exceed the given number of characters per line. Strips | |
1787 extraneous whitespace. */ | |
1788 private String formatMessage(String message, int charsPerLine) { | |
1789 StringBuffer buf = new StringBuffer(message.length()); | |
1790 StringTokenizer tokenizer = new StringTokenizer(message); | |
1791 int curLineLength = 0; | |
1792 while (tokenizer.hasMoreTokens()) { | |
1793 String tok = tokenizer.nextToken(); | |
1794 if (curLineLength + tok.length() > charsPerLine) { | |
1795 buf.append('\n'); | |
1796 curLineLength = 0; | |
1797 } else { | |
1798 if (curLineLength != 0) { | |
1799 buf.append(' '); | |
1800 ++curLineLength; | |
1801 } | |
1802 } | |
1803 buf.append(tok); | |
1804 curLineLength += tok.length(); | |
1805 } | |
1806 return buf.toString(); | |
1807 } | |
1808 | |
1809 private void setMenuItemsEnabled(java.util.List items, boolean enabled) { | |
1810 for (Iterator iter = items.iterator(); iter.hasNext(); ) { | |
1811 ((JMenuItem) iter.next()).setEnabled(enabled); | |
1812 } | |
1813 } | |
1814 } |