Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HSDB.java @ 3945:8ed53447f690
Merge
author | iveresov |
---|---|
date | Thu, 15 Sep 2011 12:44:09 -0700 |
parents | 7588156f5cf9 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1385
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot; | |
26 | |
27 import java.io.*; | |
28 import java.awt.*; | |
29 import java.awt.event.*; | |
30 import java.math.*; | |
31 import javax.swing.*; | |
32 import javax.swing.tree.*; | |
33 import java.util.*; | |
34 | |
35 import sun.jvm.hotspot.code.*; | |
36 import sun.jvm.hotspot.compiler.*; | |
37 import sun.jvm.hotspot.debugger.*; | |
38 import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; | |
39 import sun.jvm.hotspot.gc_interface.*; | |
40 import sun.jvm.hotspot.interpreter.*; | |
41 import sun.jvm.hotspot.memory.*; | |
42 import sun.jvm.hotspot.oops.*; | |
43 import sun.jvm.hotspot.runtime.*; | |
44 import sun.jvm.hotspot.ui.*; | |
45 import sun.jvm.hotspot.ui.tree.*; | |
46 import sun.jvm.hotspot.ui.classbrowser.*; | |
47 import sun.jvm.hotspot.utilities.*; | |
48 | |
49 /** The top-level HotSpot Debugger. FIXME: make this an embeddable | |
50 component! (Among other things, figure out what to do with the | |
51 menu bar...) */ | |
52 | |
53 public class HSDB implements ObjectHistogramPanel.Listener, SAListener { | |
54 public static void main(String[] args) { | |
55 new HSDB(args).run(); | |
56 } | |
57 | |
58 //-------------------------------------------------------------------------------- | |
59 // Internals only below this point | |
60 // | |
61 private HotSpotAgent agent; | |
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")); | |
1385 | 988 Address monBegin = curFrame.interpreterFrameMonitorBegin().address(); |
989 Address monEnd = curFrame.interpreterFrameMonitorEnd().address(); | |
990 if (!monBegin.equals(monEnd)) { | |
991 annoPanel.addAnnotation(new Annotation(monBegin, monEnd, | |
992 "BasicObjectLocks")); | |
993 } | |
0 | 994 if (interpreterFrameMethod != null) { |
995 // The offset is just to get the right stack slots highlighted in the output | |
996 int offset = 1; | |
997 annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameLocal(offset), | |
998 curFrame.addressOfInterpreterFrameLocal((int) interpreterFrameMethod.getMaxLocals() + offset), | |
999 "Interpreter locals area for frame with SP = " + curFrame.getSP())); | |
1000 } | |
1001 String methodAnno = "Interpreter frame methodOop"; | |
1002 if (interpreterFrameMethod == null) { | |
1003 methodAnno += " (BAD OOP)"; | |
1004 } | |
1005 Address a = curFrame.addressOfInterpreterFrameMethod(); | |
1006 annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), methodAnno)); | |
1007 a = curFrame.addressOfInterpreterFrameCPCache(); | |
1008 annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), "Interpreter constant pool cache")); | |
1009 } | |
1010 | |
1011 RegisterMap rm = (RegisterMap) vf.getRegisterMap().clone(); | |
1012 if (!shouldSkipOopMaps) { | |
1013 try { | |
1014 curFrame.oopsDo(new AddressVisitor() { | |
1015 public void visitAddress(Address addr) { | |
1016 if (Assert.ASSERTS_ENABLED) { | |
1017 Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, | |
1018 "Address " + addr + "should have been aligned"); | |
1019 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1020 OopHandle handle = addr.getOopHandleAt(0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1021 addAnnotation(addr, handle); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1022 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1023 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1024 public void visitCompOopAddress(Address addr) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1025 if (Assert.ASSERTS_ENABLED) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1026 Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1027 "Address " + addr + "should have been aligned"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1028 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1029 OopHandle handle = addr.getCompOopHandleAt(0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1030 addAnnotation(addr, handle); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1031 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1032 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1033 public void addAnnotation(Address addr, OopHandle handle) { |
0 | 1034 // Check contents |
1035 String anno = "null oop"; | |
1036 if (handle != null) { | |
1037 // Find location | |
1038 CollectedHeap collHeap = VM.getVM().getUniverse().heap(); | |
1039 boolean bad = true; | |
1040 anno = "BAD OOP"; | |
1041 if (collHeap instanceof GenCollectedHeap) { | |
1042 GenCollectedHeap heap = (GenCollectedHeap) collHeap; | |
1043 for (int i = 0; i < heap.nGens(); i++) { | |
1044 if (heap.getGen(i).isIn(handle)) { | |
1045 if (i == 0) { | |
1046 anno = "NewGen "; | |
1047 } else if (i == 1) { | |
1048 anno = "OldGen "; | |
1049 } else { | |
1050 anno = "Gen " + i + " "; | |
1051 } | |
1052 bad = false; | |
1053 break; | |
1054 } | |
1055 } | |
1056 | |
1057 if (bad) { | |
1058 // Try perm gen | |
1059 if (heap.permGen().isIn(handle)) { | |
1060 anno = "PermGen "; | |
1061 bad = false; | |
1062 } | |
1063 } | |
1064 } else if (collHeap instanceof ParallelScavengeHeap) { | |
1065 ParallelScavengeHeap heap = (ParallelScavengeHeap) collHeap; | |
1066 if (heap.youngGen().isIn(handle)) { | |
1067 anno = "PSYoungGen "; | |
1068 bad = false; | |
1069 } else if (heap.oldGen().isIn(handle)) { | |
1070 anno = "PSOldGen "; | |
1071 bad = false; | |
1072 } else if (heap.permGen().isIn(handle)) { | |
1073 anno = "PSPermGen "; | |
1074 bad = false; | |
1075 } | |
1076 } else { | |
1077 // Optimistically assume the oop isn't bad | |
1078 anno = "[Unknown generation] "; | |
1079 bad = false; | |
1080 } | |
1081 | |
1082 if (!bad) { | |
1083 try { | |
1084 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
1085 if (oop instanceof Instance) { | |
1086 // Java-level objects always have workable names | |
1087 anno = anno + oop.getKlass().getName().asString(); | |
1088 } else { | |
1089 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1090 Oop.printOopValueOn(oop, new PrintStream(bos)); | |
1091 anno = anno + bos.toString(); | |
1092 } | |
1093 } | |
1094 catch (AddressException e) { | |
1095 anno += "CORRUPT OOP"; | |
1096 } | |
1097 catch (NullPointerException e) { | |
1098 anno += "CORRUPT OOP (null pointer)"; | |
1099 } | |
1100 } | |
1101 } | |
1102 | |
1103 annoPanel.addAnnotation(new Annotation(addr, addr.addOffsetTo(addressSize), anno)); | |
1104 } | |
1105 }, rm); | |
1106 } catch (Exception e) { | |
1107 System.err.println("Error while performing oopsDo for frame " + curFrame); | |
1108 e.printStackTrace(); | |
1109 } | |
1110 } | |
1111 | |
1112 vf = nextVFrame; | |
1113 } | |
1114 | |
1115 // This used to paint as we walked the frames. This caused the display to be refreshed | |
1116 // enough to be annoying on remote displays. It also would cause the annotations to | |
1117 // be displayed in varying order which caused some annotations to overwrite others | |
1118 // depending on the races between painting and adding annotations. This latter problem | |
1119 // still exists to some degree but moving this code here definitely seems to reduce it | |
1120 annoPanel.makeVisible(startAddr); | |
1121 annoPanel.repaint(); | |
1122 } | |
1123 }); | |
1124 } | |
1125 | |
1126 /** NOTE we are in a different thread here than either the main | |
1127 thread or the Swing/AWT event handler thread, so we must be very | |
1128 careful when creating or removing widgets */ | |
1129 private void attach(String pidText) { | |
1130 try { | |
1131 this.pidText = pidText; | |
1132 pid = Integer.parseInt(pidText); | |
1133 } | |
1134 catch (NumberFormatException e) { | |
1135 SwingUtilities.invokeLater(new Runnable() { | |
1136 public void run() { | |
1137 setMenuItemsEnabled(attachMenuItems, true); | |
1138 JOptionPane.showInternalMessageDialog(desktop, | |
1139 "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.", | |
1140 "Parse error", | |
1141 JOptionPane.WARNING_MESSAGE); | |
1142 } | |
1143 }); | |
1144 return; | |
1145 } | |
1146 | |
1147 // Try to attach to this process | |
1148 Runnable remover = new Runnable() { | |
1149 public void run() { | |
1150 attachWaitDialog.setVisible(false); | |
1151 desktop.remove(attachWaitDialog); | |
1152 attachWaitDialog = null; | |
1153 } | |
1154 }; | |
1155 | |
1156 try { | |
1157 SwingUtilities.invokeLater(new Runnable() { | |
1158 public void run() { | |
1159 JOptionPane pane = new JOptionPane("Attaching to process " + pid + ", please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1160 pane.setOptions(new Object[] {}); | |
1161 attachWaitDialog = pane.createInternalFrame(desktop, "Attaching to Process"); | |
1162 attachWaitDialog.show(); | |
1163 } | |
1164 }); | |
1165 | |
1166 // FIXME: display exec'd debugger's output messages during this | |
1167 // lengthy call | |
1168 agent.attach(pid); | |
1169 if (agent.getDebugger().hasConsole()) { | |
1170 showDbgConsoleMenuItem.setEnabled(true); | |
1171 } | |
1172 attached = true; | |
1173 SwingUtilities.invokeLater(remover); | |
1174 } | |
1175 catch (DebuggerException e) { | |
1176 SwingUtilities.invokeLater(remover); | |
1177 final String errMsg = formatMessage(e.getMessage(), 80); | |
1178 SwingUtilities.invokeLater(new Runnable() { | |
1179 public void run() { | |
1180 setMenuItemsEnabled(attachMenuItems, true); | |
1181 JOptionPane.showInternalMessageDialog(desktop, | |
1182 "Unable to connect to process ID " + pid + ":\n\n" + errMsg, | |
1183 "Unable to Connect", | |
1184 JOptionPane.WARNING_MESSAGE); | |
1185 } | |
1186 }); | |
1187 agent.detach(); | |
1188 return; | |
1189 } | |
1190 | |
1191 // OK, the VM should be available. Create the Threads dialog. | |
1192 showThreadsDialog(); | |
1193 } | |
1194 | |
1195 /** NOTE we are in a different thread here than either the main | |
1196 thread or the Swing/AWT event handler thread, so we must be very | |
1197 careful when creating or removing widgets */ | |
1198 private void attach(final String executablePath, final String corePath) { | |
1199 // Try to open this core file | |
1200 Runnable remover = new Runnable() { | |
1201 public void run() { | |
1202 attachWaitDialog.setVisible(false); | |
1203 desktop.remove(attachWaitDialog); | |
1204 attachWaitDialog = null; | |
1205 } | |
1206 }; | |
1207 | |
1208 try { | |
1209 SwingUtilities.invokeLater(new Runnable() { | |
1210 public void run() { | |
1211 JOptionPane pane = new JOptionPane("Opening core file, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1212 pane.setOptions(new Object[] {}); | |
1213 attachWaitDialog = pane.createInternalFrame(desktop, "Opening Core File"); | |
1214 attachWaitDialog.show(); | |
1215 } | |
1216 }); | |
1217 | |
1218 // FIXME: display exec'd debugger's output messages during this | |
1219 // lengthy call | |
1220 agent.attach(executablePath, corePath); | |
1221 if (agent.getDebugger().hasConsole()) { | |
1222 showDbgConsoleMenuItem.setEnabled(true); | |
1223 } | |
1224 attached = true; | |
1225 SwingUtilities.invokeLater(remover); | |
1226 } | |
1227 catch (DebuggerException e) { | |
1228 SwingUtilities.invokeLater(remover); | |
1229 final String errMsg = formatMessage(e.getMessage(), 80); | |
1230 SwingUtilities.invokeLater(new Runnable() { | |
1231 public void run() { | |
1232 setMenuItemsEnabled(attachMenuItems, true); | |
1233 JOptionPane.showInternalMessageDialog(desktop, | |
1234 "Unable to open core file\n" + corePath + ":\n\n" + errMsg, | |
1235 "Unable to Open Core File", | |
1236 JOptionPane.WARNING_MESSAGE); | |
1237 } | |
1238 }); | |
1239 agent.detach(); | |
1240 return; | |
1241 } | |
1242 | |
1243 // OK, the VM should be available. Create the Threads dialog. | |
1244 showThreadsDialog(); | |
1245 } | |
1246 | |
1247 /** NOTE we are in a different thread here than either the main | |
1248 thread or the Swing/AWT event handler thread, so we must be very | |
1249 careful when creating or removing widgets */ | |
1250 private void connect(final String remoteMachineName) { | |
1251 // Try to open this core file | |
1252 Runnable remover = new Runnable() { | |
1253 public void run() { | |
1254 attachWaitDialog.setVisible(false); | |
1255 desktop.remove(attachWaitDialog); | |
1256 attachWaitDialog = null; | |
1257 } | |
1258 }; | |
1259 | |
1260 try { | |
1261 SwingUtilities.invokeLater(new Runnable() { | |
1262 public void run() { | |
1263 JOptionPane pane = new JOptionPane("Connecting to debug server, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1264 pane.setOptions(new Object[] {}); | |
1265 attachWaitDialog = pane.createInternalFrame(desktop, "Connecting to Debug Server"); | |
1266 attachWaitDialog.show(); | |
1267 } | |
1268 }); | |
1269 | |
1270 agent.attach(remoteMachineName); | |
1271 if (agent.getDebugger().hasConsole()) { | |
1272 showDbgConsoleMenuItem.setEnabled(true); | |
1273 } | |
1274 attached = true; | |
1275 SwingUtilities.invokeLater(remover); | |
1276 } | |
1277 catch (DebuggerException e) { | |
1278 SwingUtilities.invokeLater(remover); | |
1279 final String errMsg = formatMessage(e.getMessage(), 80); | |
1280 SwingUtilities.invokeLater(new Runnable() { | |
1281 public void run() { | |
1282 setMenuItemsEnabled(attachMenuItems, true); | |
1283 JOptionPane.showInternalMessageDialog(desktop, | |
1284 "Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg, | |
1285 "Unable to Connect", | |
1286 JOptionPane.WARNING_MESSAGE); | |
1287 } | |
1288 }); | |
1289 agent.detach(); | |
1290 return; | |
1291 } | |
1292 | |
1293 // OK, the VM should be available. Create the Threads dialog. | |
1294 showThreadsDialog(); | |
1295 } | |
1296 | |
1297 private void detachDebugger() { | |
1298 if (!attached) { | |
1299 return; | |
1300 } | |
1301 agent.detach(); | |
1302 attached = false; | |
1303 } | |
1304 | |
1305 private void detach() { | |
1306 detachDebugger(); | |
1307 attachWaitDialog = null; | |
1308 threadsFrame = null; | |
1309 consoleFrame = null; | |
1310 setMenuItemsEnabled(attachMenuItems, true); | |
1311 setMenuItemsEnabled(detachMenuItems, false); | |
1312 toolsMenu.setEnabled(false); | |
1313 showDbgConsoleMenuItem.setEnabled(false); | |
1314 // FIXME: is this sufficient, or will I have to do anything else | |
1315 // to the components to kill them off? What about WorkerThreads? | |
1316 desktop.removeAll(); | |
1317 desktop.invalidate(); | |
1318 desktop.validate(); | |
1319 desktop.repaint(); | |
1320 } | |
1321 | |
1322 /** NOTE that this is called from another thread than the main or | |
1323 Swing thread and we have to be careful about synchronization */ | |
1324 private void showThreadsDialog() { | |
1325 SwingUtilities.invokeLater(new Runnable() { | |
1326 public void run() { | |
1327 threadsFrame = new JInternalFrame("Java Threads"); | |
1328 threadsFrame.setResizable(true); | |
1329 threadsFrame.setIconifiable(true); | |
1330 JavaThreadsPanel threadsPanel = new JavaThreadsPanel(); | |
1331 threadsPanel.addPanelListener(HSDB.this); | |
1332 threadsFrame.getContentPane().add(threadsPanel); | |
1333 threadsFrame.setSize(500, 300); | |
1334 threadsFrame.pack(); | |
1335 desktop.add(threadsFrame); | |
1336 GraphicsUtilities.moveToInContainer(threadsFrame, 0.75f, 0.25f, 0, 20); | |
1337 threadsFrame.show(); | |
1338 setMenuItemsEnabled(attachMenuItems, false); | |
1339 setMenuItemsEnabled(detachMenuItems, true); | |
1340 toolsMenu.setEnabled(true); | |
1341 VM.registerVMInitializedObserver(new Observer() { | |
1342 public void update(Observable o, Object data) { | |
1343 computeRevPtrsMenuItem.setEnabled(true); | |
1344 } | |
1345 }); | |
1346 } | |
1347 }); | |
1348 } | |
1349 | |
1350 private void showObjectHistogram() { | |
1351 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1352 ObjectHistogramCleanupThunk cleanup = | |
1353 new ObjectHistogramCleanupThunk(histo); | |
1354 doHeapIteration("Object Histogram", | |
1355 "Generating histogram...", | |
1356 histo, | |
1357 cleanup); | |
1358 } | |
1359 | |
1360 class ObjectHistogramCleanupThunk implements CleanupThunk { | |
1361 sun.jvm.hotspot.oops.ObjectHistogram histo; | |
1362 | |
1363 ObjectHistogramCleanupThunk(sun.jvm.hotspot.oops.ObjectHistogram histo) { | |
1364 this.histo = histo; | |
1365 } | |
1366 | |
1367 public void heapIterationComplete() { | |
1368 SwingUtilities.invokeLater(new Runnable() { | |
1369 public void run() { | |
1370 JInternalFrame histoFrame = new JInternalFrame("Object Histogram"); | |
1371 histoFrame.setResizable(true); | |
1372 histoFrame.setClosable(true); | |
1373 histoFrame.setIconifiable(true); | |
1374 histoFrame.getContentPane().setLayout(new BorderLayout()); | |
1375 ObjectHistogramPanel panel = new ObjectHistogramPanel(histo); | |
1376 panel.addPanelListener(HSDB.this); | |
1377 histoFrame.getContentPane().add(panel); | |
1378 desktop.add(histoFrame); | |
1379 GraphicsUtilities.reshapeToAspectRatio(histoFrame, 4.0f / 3.0f, 0.6f, | |
1380 histoFrame.getParent().getSize()); | |
1381 GraphicsUtilities.centerInContainer(histoFrame); | |
1382 histoFrame.show(); | |
1383 } | |
1384 }); | |
1385 } | |
1386 } | |
1387 | |
1388 public void showObjectsOfType(Klass type) { | |
1389 FindObjectByType finder = new FindObjectByType(type); | |
1390 FindObjectByTypeCleanupThunk cleanup = | |
1391 new FindObjectByTypeCleanupThunk(finder); | |
1392 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1393 type.printValueOn(new PrintStream(bos)); | |
1394 String typeName = bos.toString(); | |
1395 doHeapIteration("Show Objects Of Type", | |
1396 "Finding instances of \"" + typeName + "\"", | |
1397 finder, | |
1398 cleanup); | |
1399 } | |
1400 | |
1401 class FindObjectByTypeCleanupThunk implements CleanupThunk { | |
1402 FindObjectByType finder; | |
1403 | |
1404 FindObjectByTypeCleanupThunk(FindObjectByType finder) { | |
1405 this.finder = finder; | |
1406 } | |
1407 | |
1408 public void heapIterationComplete() { | |
1409 SwingUtilities.invokeLater(new Runnable() { | |
1410 public void run() { | |
1411 JInternalFrame finderFrame = new JInternalFrame("Show Objects of Type"); | |
1412 finderFrame.getContentPane().setLayout(new BorderLayout()); | |
1413 finderFrame.setResizable(true); | |
1414 finderFrame.setClosable(true); | |
1415 finderFrame.setIconifiable(true); | |
1416 ObjectListPanel panel = new ObjectListPanel(finder.getResults(), | |
1417 new HeapProgress("Reverse Pointers Analysis")); | |
1418 panel.addPanelListener(HSDB.this); | |
1419 finderFrame.getContentPane().add(panel); | |
1420 desktop.add(finderFrame); | |
1421 GraphicsUtilities.reshapeToAspectRatio(finderFrame, 4.0f / 3.0f, 0.6f, | |
1422 finderFrame.getParent().getSize()); | |
1423 GraphicsUtilities.centerInContainer(finderFrame); | |
1424 finderFrame.show(); | |
1425 } | |
1426 }); | |
1427 } | |
1428 } | |
1429 | |
1430 private void showDebuggerConsole() { | |
1431 if (consoleFrame == null) { | |
1432 consoleFrame = new JInternalFrame("Debugger Console"); | |
1433 consoleFrame.setResizable(true); | |
1434 consoleFrame.setClosable(true); | |
1435 consoleFrame.setIconifiable(true); | |
1436 consoleFrame.getContentPane().setLayout(new BorderLayout()); | |
1437 consoleFrame.getContentPane().add(new DebuggerConsolePanel(agent.getDebugger()), BorderLayout.CENTER); | |
1438 GraphicsUtilities.reshapeToAspectRatio(consoleFrame, 5.0f, 0.9f, desktop.getSize()); | |
1439 } | |
1440 if (consoleFrame.getParent() == null) { | |
1441 desktop.add(consoleFrame); | |
1442 } | |
1443 consoleFrame.setVisible(true); | |
1444 consoleFrame.show(); | |
1445 consoleFrame.getContentPane().getComponent(0).requestFocus(); | |
1446 } | |
1447 | |
1448 private void showConsole() { | |
1449 CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() { | |
1450 public HotSpotAgent getAgent() { | |
1451 return agent; | |
1452 } | |
1453 public boolean isAttached() { | |
1454 return attached; | |
1455 } | |
1456 public void attach(String pid) { | |
1457 attach(pid); | |
1458 } | |
1459 public void attach(String java, String core) { | |
1460 } | |
1461 public void detach() { | |
1462 detachDebugger(); | |
1463 } | |
1464 public void reattach() { | |
1465 if (attached) { | |
1466 detachDebugger(); | |
1467 } | |
1468 if (pidText != null) { | |
1469 attach(pidText); | |
1470 } else { | |
1471 attach(execPath, coreFilename); | |
1472 } | |
1473 } | |
1474 }; | |
1475 | |
1476 showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null))); | |
1477 } | |
1478 | |
1479 private void showFindByQueryPanel() { | |
1480 showPanel("Find Object by Query", new FindByQueryPanel()); | |
1481 } | |
1482 | |
1483 private void showFindPanel() { | |
1484 showPanel("Find Pointer", new FindPanel()); | |
1485 } | |
1486 | |
1487 private void showFindInHeapPanel() { | |
1488 showPanel("Find Address In Heap", new FindInHeapPanel()); | |
1489 } | |
1490 | |
1491 private void showFindInCodeCachePanel() { | |
1492 showPanel("Find Address In Code Cache", new FindInCodeCachePanel()); | |
1493 } | |
1494 | |
1495 private void showHeapParametersPanel() { | |
1496 showPanel("Heap Parameters", new HeapParametersPanel()); | |
1497 } | |
1498 | |
1499 public void showThreadInfo(final JavaThread thread) { | |
1500 showPanel("Info for " + thread.getThreadName(), new ThreadInfoPanel(thread)); | |
1501 } | |
1502 | |
1503 public void showJavaStackTrace(final JavaThread thread) { | |
1504 JavaStackTracePanel jstp = new JavaStackTracePanel(); | |
1505 showPanel("Java stack trace for " + thread.getThreadName(), jstp); | |
1506 jstp.setJavaThread(thread); | |
1507 } | |
1508 | |
1509 private void showDeadlockDetectionPanel() { | |
1510 showPanel("Deadlock Detection", new DeadlockDetectionPanel()); | |
1511 } | |
1512 | |
1513 private void showMonitorCacheDumpPanel() { | |
1514 showPanel("Monitor Cache Dump", new MonitorCacheDumpPanel()); | |
1515 } | |
1516 | |
1517 public void showClassBrowser() { | |
1518 final JInternalFrame progressFrame = new JInternalFrame("Class Browser"); | |
1519 progressFrame.setResizable(true); | |
1520 progressFrame.setClosable(true); | |
1521 progressFrame.setIconifiable(true); | |
1522 progressFrame.getContentPane().setLayout(new BorderLayout()); | |
1523 final ProgressBarPanel bar = new ProgressBarPanel("Generating class list .."); | |
1524 bar.setIndeterminate(true); | |
1525 progressFrame.getContentPane().add(bar, BorderLayout.CENTER); | |
1526 desktop.add(progressFrame); | |
1527 progressFrame.pack(); | |
1528 GraphicsUtilities.centerInContainer(progressFrame); | |
1529 progressFrame.show(); | |
1530 | |
1531 workerThread.invokeLater(new Runnable() { | |
1532 public void run() { | |
1533 HTMLGenerator htmlGen = new HTMLGenerator(); | |
1534 InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses(); | |
1535 final String htmlText = htmlGen.genHTMLForKlassNames(klasses); | |
1536 SwingUtilities.invokeLater(new Runnable() { | |
1537 public void run() { | |
1538 JInternalFrame cbFrame = new JInternalFrame("Class Browser"); | |
1539 cbFrame.getContentPane().setLayout(new BorderLayout()); | |
1540 cbFrame.setResizable(true); | |
1541 cbFrame.setClosable(true); | |
1542 cbFrame.setIconifiable(true); | |
1543 ClassBrowserPanel cbPanel = new ClassBrowserPanel(); | |
1544 cbFrame.getContentPane().add(cbPanel, BorderLayout.CENTER); | |
1545 desktop.remove(progressFrame); | |
1546 desktop.repaint(); | |
1547 desktop.add(cbFrame); | |
1548 GraphicsUtilities.reshapeToAspectRatio(cbFrame, 1.25f, 0.85f, | |
1549 cbFrame.getParent().getSize()); | |
1550 cbFrame.show(); | |
1551 cbPanel.setClassesText(htmlText); | |
1552 } | |
1553 }); | |
1554 } | |
1555 }); | |
1556 } | |
1557 | |
1558 public void showCodeViewer() { | |
1559 showPanel("Code Viewer", new CodeViewerPanel(), 1.25f, 0.85f); | |
1560 } | |
1561 | |
1562 public void showCodeViewer(final Address address) { | |
1563 final CodeViewerPanel panel = new CodeViewerPanel(); | |
1564 showPanel("Code Viewer", panel, 1.25f, 0.85f); | |
1565 SwingUtilities.invokeLater(new Runnable() { | |
1566 public void run() { | |
1567 panel.viewAddress(address); | |
1568 } | |
1569 }); | |
1570 | |
1571 } | |
1572 | |
1573 public void showMemoryViewer() { | |
1574 showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8)); | |
1575 } | |
1576 | |
1577 public void showCommandLineFlags() { | |
1578 showPanel("Command Line Flags", new VMFlagsPanel()); | |
1579 } | |
1580 | |
1581 public void showVMVersion() { | |
1582 showPanel("VM Version Info", new VMVersionInfoPanel()); | |
1583 } | |
1584 | |
1585 public void showSystemProperties() { | |
1586 showPanel("System Properties", new SysPropsPanel()); | |
1587 } | |
1588 | |
1589 private void showPanel(String name, JPanel panel) { | |
1590 showPanel(name, panel, 5.0f / 3.0f, 0.4f); | |
1591 } | |
1592 | |
1593 private void showPanel(String name, JPanel panel, float aspectRatio, float fillRatio) { | |
1594 JInternalFrame frame = new JInternalFrame(name); | |
1595 frame.getContentPane().setLayout(new BorderLayout()); | |
1596 frame.setResizable(true); | |
1597 frame.setClosable(true); | |
1598 frame.setIconifiable(true); | |
1599 frame.setMaximizable(true); | |
1600 frame.getContentPane().add(panel, BorderLayout.CENTER); | |
1601 desktop.add(frame); | |
1602 GraphicsUtilities.reshapeToAspectRatio(frame, aspectRatio, fillRatio, frame.getParent().getSize()); | |
1603 GraphicsUtilities.randomLocation(frame); | |
1604 frame.show(); | |
1605 if (panel instanceof SAPanel) { | |
1606 ((SAPanel)panel).addPanelListener(this); | |
1607 } | |
1608 } | |
1609 | |
1610 //-------------------------------------------------------------------------------- | |
1611 // Framework for heap iteration with progress bar | |
1612 // | |
1613 | |
1614 interface CleanupThunk { | |
1615 public void heapIterationComplete(); | |
1616 } | |
1617 | |
1618 class HeapProgress implements HeapProgressThunk { | |
1619 private JInternalFrame frame; | |
1620 private ProgressBarPanel bar; | |
1621 private String windowTitle; | |
1622 private String progressBarTitle; | |
1623 private CleanupThunk cleanup; | |
1624 | |
1625 HeapProgress(String windowTitle) { | |
1626 this(windowTitle, "Percentage of heap visited", null); | |
1627 } | |
1628 | |
1629 HeapProgress(String windowTitle, String progressBarTitle) { | |
1630 this(windowTitle, progressBarTitle, null); | |
1631 } | |
1632 | |
1633 HeapProgress(String windowTitle, String progressBarTitle, CleanupThunk cleanup) { | |
1634 this.windowTitle = windowTitle; | |
1635 this.progressBarTitle = progressBarTitle; | |
1636 this.cleanup = cleanup; | |
1637 } | |
1638 | |
1639 public void heapIterationFractionUpdate(final double fractionOfHeapVisited) { | |
1640 if (frame == null) { | |
1641 SwingUtilities.invokeLater(new Runnable() { | |
1642 public void run() { | |
1643 frame = new JInternalFrame(windowTitle); | |
1644 frame.setResizable(true); | |
1645 frame.setIconifiable(true); | |
1646 frame.getContentPane().setLayout(new BorderLayout()); | |
1647 bar = new ProgressBarPanel(progressBarTitle); | |
1648 frame.getContentPane().add(bar, BorderLayout.CENTER); | |
1649 desktop.add(frame); | |
1650 frame.pack(); | |
1651 GraphicsUtilities.constrainToSize(frame, frame.getParent().getSize()); | |
1652 GraphicsUtilities.centerInContainer(frame); | |
1653 frame.show(); | |
1654 } | |
1655 }); | |
1656 } | |
1657 | |
1658 SwingUtilities.invokeLater(new Runnable() { | |
1659 public void run() { | |
1660 bar.setValue(fractionOfHeapVisited); | |
1661 } | |
1662 }); | |
1663 } | |
1664 | |
1665 public void heapIterationComplete() { | |
1666 SwingUtilities.invokeLater(new Runnable() { | |
1667 public void run() { | |
1668 desktop.remove(frame); | |
1669 desktop.repaint(); | |
1670 if (VM.getVM().getRevPtrs() != null) { | |
1671 // Ended up computing reverse pointers as a side-effect | |
1672 computeRevPtrsMenuItem.setEnabled(false); | |
1673 } | |
1674 } | |
1675 }); | |
1676 | |
1677 if (cleanup != null) { | |
1678 cleanup.heapIterationComplete(); | |
1679 } | |
1680 } | |
1681 } | |
1682 | |
1683 class VisitHeap implements Runnable { | |
1684 HeapVisitor visitor; | |
1685 | |
1686 VisitHeap(HeapVisitor visitor) { | |
1687 this.visitor = visitor; | |
1688 } | |
1689 | |
1690 public void run() { | |
1691 VM.getVM().getObjectHeap().iterate(visitor); | |
1692 } | |
1693 } | |
1694 | |
1695 private void doHeapIteration(String frameTitle, | |
1696 String progressBarText, | |
1697 HeapVisitor visitor, | |
1698 CleanupThunk cleanup) { | |
1699 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1700 HeapProgress progress = new HeapProgress(frameTitle, | |
1701 progressBarText, | |
1702 cleanup); | |
1703 HeapVisitor progVisitor = new ProgressiveHeapVisitor(visitor, progress); | |
1704 workerThread.invokeLater(new VisitHeap(progVisitor)); | |
1705 } | |
1706 | |
1707 //-------------------------------------------------------------------------------- | |
1708 // Stack trace helper | |
1709 // | |
1710 | |
1711 private static JavaVFrame getLastJavaVFrame(JavaThread cur) { | |
1712 RegisterMap regMap = cur.newRegisterMap(true); | |
1713 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1714 if (f == null) return null; | |
1715 boolean imprecise = true; | |
1716 if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) { | |
1717 System.err.println("Correcting for invalid interpreter frame"); | |
1718 f = f.sender(regMap); | |
1719 imprecise = false; | |
1720 } | |
1721 VFrame vf = VFrame.newVFrame(f, regMap, cur, true, imprecise); | |
1722 if (vf == null) { | |
1723 System.err.println(" (Unable to create vframe for topmost frame guess)"); | |
1724 return null; | |
1725 } | |
1726 if (vf.isJavaFrame()) { | |
1727 return (JavaVFrame) vf; | |
1728 } | |
1729 return (JavaVFrame) vf.javaSender(); | |
1730 } | |
1731 | |
1732 // Internal routine for debugging | |
1733 private static void dumpStack(JavaThread cur) { | |
1734 RegisterMap regMap = cur.newRegisterMap(true); | |
1735 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1736 PrintStream tty = System.err; | |
1737 while (f != null) { | |
1738 tty.print("Found "); | |
1739 if (f.isInterpretedFrame()) { tty.print("interpreted"); } | |
1740 else if (f.isCompiledFrame()) { tty.print("compiled"); } | |
1741 else if (f.isEntryFrame()) { tty.print("entry"); } | |
1742 else if (f.isNativeFrame()) { tty.print("native"); } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
1743 else if (f.isRuntimeFrame()) { tty.print("runtime"); } |
0 | 1744 else { tty.print("external"); } |
1745 tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP()); | |
1746 if (f.isSignalHandlerFrameDbg()) { | |
1747 tty.print(" (SIGNAL HANDLER)"); | |
1748 } | |
1749 tty.println(); | |
1750 | |
1751 if (!f.isFirstFrame()) { | |
1752 f = f.sender(regMap); | |
1753 } else { | |
1754 f = null; | |
1755 } | |
1756 } | |
1757 } | |
1758 | |
1759 //-------------------------------------------------------------------------------- | |
1760 // Component utilities | |
1761 // | |
1762 | |
1763 private static JMenuItem createMenuItem(String name, ActionListener l) { | |
1764 JMenuItem item = new JMenuItem(name); | |
1765 item.addActionListener(l); | |
1766 return item; | |
1767 } | |
1768 | |
1769 /** Punctuates the given string with \n's where necessary to not | |
1770 exceed the given number of characters per line. Strips | |
1771 extraneous whitespace. */ | |
1772 private String formatMessage(String message, int charsPerLine) { | |
1773 StringBuffer buf = new StringBuffer(message.length()); | |
1774 StringTokenizer tokenizer = new StringTokenizer(message); | |
1775 int curLineLength = 0; | |
1776 while (tokenizer.hasMoreTokens()) { | |
1777 String tok = tokenizer.nextToken(); | |
1778 if (curLineLength + tok.length() > charsPerLine) { | |
1779 buf.append('\n'); | |
1780 curLineLength = 0; | |
1781 } else { | |
1782 if (curLineLength != 0) { | |
1783 buf.append(' '); | |
1784 ++curLineLength; | |
1785 } | |
1786 } | |
1787 buf.append(tok); | |
1788 curLineLength += tok.length(); | |
1789 } | |
1790 return buf.toString(); | |
1791 } | |
1792 | |
1793 private void setMenuItemsEnabled(java.util.List items, boolean enabled) { | |
1794 for (Iterator iter = items.iterator(); iter.hasNext(); ) { | |
1795 ((JMenuItem) iter.next()).setEnabled(enabled); | |
1796 } | |
1797 } | |
1798 } |