comparison agent/src/share/classes/sun/jvm/hotspot/HSDB.java @ 0:a61af66fc99e jdk7-b24

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