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);
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 });
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.setVisible(true);
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);
1094 }
1095 }, rm);
1096 } catch (Exception e) {
1097 System.err.println("Error while performing oopsDo for frame " + curFrame);
1098 e.printStackTrace();
1099 }
1100 }
1101
1102 vf = nextVFrame;
1103 }
1104
1105 // This used to paint as we walked the frames. This caused the display to be refreshed
1106 // enough to be annoying on remote displays. It also would cause the annotations to
1107 // be displayed in varying order which caused some annotations to overwrite others
1108 // depending on the races between painting and adding annotations. This latter problem
1109 // still exists to some degree but moving this code here definitely seems to reduce it
1110 annoPanel.makeVisible(startAddr);
1111 annoPanel.repaint();
1112 }
1113 });
1114 }
1115
1116 /** NOTE we are in a different thread here than either the main
1117 thread or the Swing/AWT event handler thread, so we must be very
1118 careful when creating or removing widgets */
1119 private void attach(String pidText) {
1120 try {
1121 this.pidText = pidText;
1122 pid = Integer.parseInt(pidText);
1123 }
1124 catch (NumberFormatException e) {
1125 SwingUtilities.invokeLater(new Runnable() {
1126 public void run() {
1127 setMenuItemsEnabled(attachMenuItems, true);
1128 JOptionPane.showInternalMessageDialog(desktop,
1129 "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.",
1130 "Parse error",
1131 JOptionPane.WARNING_MESSAGE);
1132 }
1133 });
|
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 JVMDebugger jvmDebugger;
63 private JDesktopPane desktop;
64 private boolean attached;
65 private boolean argError;
66 private JFrame frame;
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();
91 argError = true;
92 }
93
94 public HSDB(JVMDebugger d) {
95 jvmDebugger = d;
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
130 // close this tool without calling System.exit
131 protected void closeUI() {
132 workerThread.shutdown();
133 frame.dispose();
134 }
135
136 public void run() {
137 // Don't start the UI if there were bad arguments.
138 if (argError) {
139 return;
140 }
141
142 agent = new HotSpotAgent();
143 workerThread = new WorkerThread();
144 attachMenuItems = new java.util.ArrayList();
145 detachMenuItems = new java.util.ArrayList();
146
147 frame = new JFrame("HSDB - HotSpot Debugger");
148 frame.setSize(800, 600);
149 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
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);
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) {
212 closeUI();
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 });
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());
413 frame.setVisible(true);
414
415 Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
416 public void run() {
417 detachDebugger();
418 }
419 });
420
421 // If jvmDebugger is already set, we have been given a JVMDebugger.
422 // Otherwise, if pidText != null we are supposed to attach to it.
423 // Finally, if execPath != null, it is the path of a jdk/bin/java
424 // and coreFilename is the pathname of a core file we are
425 // supposed to attach to.
426
427 if (jvmDebugger != null) {
428 attach(jvmDebugger);
429 } else if (pidText != null) {
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);
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
1136 // Attach to existing JVMDebugger, which should be already attached to a core/process.
1137 private void attach(JVMDebugger d) {
1138 attached = true;
1139 showThreadsDialog();
1140 }
1141
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 });
|