Mercurial > hg > graal-jvmci-8
annotate agent/src/share/classes/sun/jvm/hotspot/HSDB.java @ 152:c70a245cad3a
6670684: 4/5 SA command universe did not print out CMS space information
Summary: Forward port of Yumin's fix for 6670684 from HSX-11; Yumin verified the port was correct.
Reviewed-by: dcubed
author | dcubed |
---|---|
date | Fri, 09 May 2008 08:55:13 -0700 |
parents | a61af66fc99e |
children | 5bba3366a9a2 |
rev | line source |
---|---|
0 | 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()); | |
152
c70a245cad3a
6670684: 4/5 SA command universe did not print out CMS space information
dcubed
parents:
0
diff
changeset
|
401 frame.setVisible(true); |
0 | 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 } |