Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/HSDB.java @ 7416:a70c88896791
8004713: Stackoverflowerror thrown when thread stack straddles 0x80000000
Summary: use unsigned comparison when checking for stack overflow
Reviewed-by: kvn, twisti
Contributed-by: paul.nauman@oracle.com
author | kvn |
---|---|
date | Thu, 13 Dec 2012 17:27:55 -0800 |
parents | da91efe96a93 |
children | 38ea2efa32a7 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3908
diff
changeset
|
2 * Copyright (c) 2000, 2012, 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 } | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3908
diff
changeset
|
1001 String methodAnno = "Interpreter frame Method*"; |
0 | 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 } else if (collHeap instanceof ParallelScavengeHeap) { | |
1058 ParallelScavengeHeap heap = (ParallelScavengeHeap) collHeap; | |
1059 if (heap.youngGen().isIn(handle)) { | |
1060 anno = "PSYoungGen "; | |
1061 bad = false; | |
1062 } else if (heap.oldGen().isIn(handle)) { | |
1063 anno = "PSOldGen "; | |
1064 bad = false; | |
1065 } | |
1066 } else { | |
1067 // Optimistically assume the oop isn't bad | |
1068 anno = "[Unknown generation] "; | |
1069 bad = false; | |
1070 } | |
1071 | |
1072 if (!bad) { | |
1073 try { | |
1074 Oop oop = VM.getVM().getObjectHeap().newOop(handle); | |
1075 if (oop instanceof Instance) { | |
1076 // Java-level objects always have workable names | |
1077 anno = anno + oop.getKlass().getName().asString(); | |
1078 } else { | |
1079 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1080 Oop.printOopValueOn(oop, new PrintStream(bos)); | |
1081 anno = anno + bos.toString(); | |
1082 } | |
1083 } | |
1084 catch (AddressException e) { | |
1085 anno += "CORRUPT OOP"; | |
1086 } | |
1087 catch (NullPointerException e) { | |
1088 anno += "CORRUPT OOP (null pointer)"; | |
1089 } | |
1090 } | |
1091 } | |
1092 | |
1093 annoPanel.addAnnotation(new Annotation(addr, addr.addOffsetTo(addressSize), anno)); | |
1094 } | |
1095 }, rm); | |
1096 } catch (Exception e) { | |
1097 System.err.println("Error while performing oopsDo for frame " + curFrame); | |
1098 e.printStackTrace(); | |
1099 } | |
1100 } | |
1101 | |
1102 vf = nextVFrame; | |
1103 } | |
1104 | |
1105 // This used to paint as we walked the frames. This caused the display to be refreshed | |
1106 // enough to be annoying on remote displays. It also would cause the annotations to | |
1107 // be displayed in varying order which caused some annotations to overwrite others | |
1108 // depending on the races between painting and adding annotations. This latter problem | |
1109 // still exists to some degree but moving this code here definitely seems to reduce it | |
1110 annoPanel.makeVisible(startAddr); | |
1111 annoPanel.repaint(); | |
1112 } | |
1113 }); | |
1114 } | |
1115 | |
1116 /** NOTE we are in a different thread here than either the main | |
1117 thread or the Swing/AWT event handler thread, so we must be very | |
1118 careful when creating or removing widgets */ | |
1119 private void attach(String pidText) { | |
1120 try { | |
1121 this.pidText = pidText; | |
1122 pid = Integer.parseInt(pidText); | |
1123 } | |
1124 catch (NumberFormatException e) { | |
1125 SwingUtilities.invokeLater(new Runnable() { | |
1126 public void run() { | |
1127 setMenuItemsEnabled(attachMenuItems, true); | |
1128 JOptionPane.showInternalMessageDialog(desktop, | |
1129 "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.", | |
1130 "Parse error", | |
1131 JOptionPane.WARNING_MESSAGE); | |
1132 } | |
1133 }); | |
1134 return; | |
1135 } | |
1136 | |
1137 // Try to attach to this process | |
1138 Runnable remover = new Runnable() { | |
1139 public void run() { | |
1140 attachWaitDialog.setVisible(false); | |
1141 desktop.remove(attachWaitDialog); | |
1142 attachWaitDialog = null; | |
1143 } | |
1144 }; | |
1145 | |
1146 try { | |
1147 SwingUtilities.invokeLater(new Runnable() { | |
1148 public void run() { | |
1149 JOptionPane pane = new JOptionPane("Attaching to process " + pid + ", please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1150 pane.setOptions(new Object[] {}); | |
1151 attachWaitDialog = pane.createInternalFrame(desktop, "Attaching to Process"); | |
1152 attachWaitDialog.show(); | |
1153 } | |
1154 }); | |
1155 | |
1156 // FIXME: display exec'd debugger's output messages during this | |
1157 // lengthy call | |
1158 agent.attach(pid); | |
1159 if (agent.getDebugger().hasConsole()) { | |
1160 showDbgConsoleMenuItem.setEnabled(true); | |
1161 } | |
1162 attached = true; | |
1163 SwingUtilities.invokeLater(remover); | |
1164 } | |
1165 catch (DebuggerException e) { | |
1166 SwingUtilities.invokeLater(remover); | |
1167 final String errMsg = formatMessage(e.getMessage(), 80); | |
1168 SwingUtilities.invokeLater(new Runnable() { | |
1169 public void run() { | |
1170 setMenuItemsEnabled(attachMenuItems, true); | |
1171 JOptionPane.showInternalMessageDialog(desktop, | |
1172 "Unable to connect to process ID " + pid + ":\n\n" + errMsg, | |
1173 "Unable to Connect", | |
1174 JOptionPane.WARNING_MESSAGE); | |
1175 } | |
1176 }); | |
1177 agent.detach(); | |
1178 return; | |
1179 } | |
1180 | |
1181 // OK, the VM should be available. Create the Threads dialog. | |
1182 showThreadsDialog(); | |
1183 } | |
1184 | |
1185 /** NOTE we are in a different thread here than either the main | |
1186 thread or the Swing/AWT event handler thread, so we must be very | |
1187 careful when creating or removing widgets */ | |
1188 private void attach(final String executablePath, final String corePath) { | |
1189 // Try to open this core file | |
1190 Runnable remover = new Runnable() { | |
1191 public void run() { | |
1192 attachWaitDialog.setVisible(false); | |
1193 desktop.remove(attachWaitDialog); | |
1194 attachWaitDialog = null; | |
1195 } | |
1196 }; | |
1197 | |
1198 try { | |
1199 SwingUtilities.invokeLater(new Runnable() { | |
1200 public void run() { | |
1201 JOptionPane pane = new JOptionPane("Opening core file, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1202 pane.setOptions(new Object[] {}); | |
1203 attachWaitDialog = pane.createInternalFrame(desktop, "Opening Core File"); | |
1204 attachWaitDialog.show(); | |
1205 } | |
1206 }); | |
1207 | |
1208 // FIXME: display exec'd debugger's output messages during this | |
1209 // lengthy call | |
1210 agent.attach(executablePath, corePath); | |
1211 if (agent.getDebugger().hasConsole()) { | |
1212 showDbgConsoleMenuItem.setEnabled(true); | |
1213 } | |
1214 attached = true; | |
1215 SwingUtilities.invokeLater(remover); | |
1216 } | |
1217 catch (DebuggerException e) { | |
1218 SwingUtilities.invokeLater(remover); | |
1219 final String errMsg = formatMessage(e.getMessage(), 80); | |
1220 SwingUtilities.invokeLater(new Runnable() { | |
1221 public void run() { | |
1222 setMenuItemsEnabled(attachMenuItems, true); | |
1223 JOptionPane.showInternalMessageDialog(desktop, | |
1224 "Unable to open core file\n" + corePath + ":\n\n" + errMsg, | |
1225 "Unable to Open Core File", | |
1226 JOptionPane.WARNING_MESSAGE); | |
1227 } | |
1228 }); | |
1229 agent.detach(); | |
1230 return; | |
1231 } | |
1232 | |
1233 // OK, the VM should be available. Create the Threads dialog. | |
1234 showThreadsDialog(); | |
1235 } | |
1236 | |
1237 /** NOTE we are in a different thread here than either the main | |
1238 thread or the Swing/AWT event handler thread, so we must be very | |
1239 careful when creating or removing widgets */ | |
1240 private void connect(final String remoteMachineName) { | |
1241 // Try to open this core file | |
1242 Runnable remover = new Runnable() { | |
1243 public void run() { | |
1244 attachWaitDialog.setVisible(false); | |
1245 desktop.remove(attachWaitDialog); | |
1246 attachWaitDialog = null; | |
1247 } | |
1248 }; | |
1249 | |
1250 try { | |
1251 SwingUtilities.invokeLater(new Runnable() { | |
1252 public void run() { | |
1253 JOptionPane pane = new JOptionPane("Connecting to debug server, please wait...", JOptionPane.INFORMATION_MESSAGE); | |
1254 pane.setOptions(new Object[] {}); | |
1255 attachWaitDialog = pane.createInternalFrame(desktop, "Connecting to Debug Server"); | |
1256 attachWaitDialog.show(); | |
1257 } | |
1258 }); | |
1259 | |
1260 agent.attach(remoteMachineName); | |
1261 if (agent.getDebugger().hasConsole()) { | |
1262 showDbgConsoleMenuItem.setEnabled(true); | |
1263 } | |
1264 attached = true; | |
1265 SwingUtilities.invokeLater(remover); | |
1266 } | |
1267 catch (DebuggerException e) { | |
1268 SwingUtilities.invokeLater(remover); | |
1269 final String errMsg = formatMessage(e.getMessage(), 80); | |
1270 SwingUtilities.invokeLater(new Runnable() { | |
1271 public void run() { | |
1272 setMenuItemsEnabled(attachMenuItems, true); | |
1273 JOptionPane.showInternalMessageDialog(desktop, | |
1274 "Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg, | |
1275 "Unable to Connect", | |
1276 JOptionPane.WARNING_MESSAGE); | |
1277 } | |
1278 }); | |
1279 agent.detach(); | |
1280 return; | |
1281 } | |
1282 | |
1283 // OK, the VM should be available. Create the Threads dialog. | |
1284 showThreadsDialog(); | |
1285 } | |
1286 | |
1287 private void detachDebugger() { | |
1288 if (!attached) { | |
1289 return; | |
1290 } | |
1291 agent.detach(); | |
1292 attached = false; | |
1293 } | |
1294 | |
1295 private void detach() { | |
1296 detachDebugger(); | |
1297 attachWaitDialog = null; | |
1298 threadsFrame = null; | |
1299 consoleFrame = null; | |
1300 setMenuItemsEnabled(attachMenuItems, true); | |
1301 setMenuItemsEnabled(detachMenuItems, false); | |
1302 toolsMenu.setEnabled(false); | |
1303 showDbgConsoleMenuItem.setEnabled(false); | |
1304 // FIXME: is this sufficient, or will I have to do anything else | |
1305 // to the components to kill them off? What about WorkerThreads? | |
1306 desktop.removeAll(); | |
1307 desktop.invalidate(); | |
1308 desktop.validate(); | |
1309 desktop.repaint(); | |
1310 } | |
1311 | |
1312 /** NOTE that this is called from another thread than the main or | |
1313 Swing thread and we have to be careful about synchronization */ | |
1314 private void showThreadsDialog() { | |
1315 SwingUtilities.invokeLater(new Runnable() { | |
1316 public void run() { | |
1317 threadsFrame = new JInternalFrame("Java Threads"); | |
1318 threadsFrame.setResizable(true); | |
1319 threadsFrame.setIconifiable(true); | |
1320 JavaThreadsPanel threadsPanel = new JavaThreadsPanel(); | |
1321 threadsPanel.addPanelListener(HSDB.this); | |
1322 threadsFrame.getContentPane().add(threadsPanel); | |
1323 threadsFrame.setSize(500, 300); | |
1324 threadsFrame.pack(); | |
1325 desktop.add(threadsFrame); | |
1326 GraphicsUtilities.moveToInContainer(threadsFrame, 0.75f, 0.25f, 0, 20); | |
1327 threadsFrame.show(); | |
1328 setMenuItemsEnabled(attachMenuItems, false); | |
1329 setMenuItemsEnabled(detachMenuItems, true); | |
1330 toolsMenu.setEnabled(true); | |
1331 VM.registerVMInitializedObserver(new Observer() { | |
1332 public void update(Observable o, Object data) { | |
1333 computeRevPtrsMenuItem.setEnabled(true); | |
1334 } | |
1335 }); | |
1336 } | |
1337 }); | |
1338 } | |
1339 | |
1340 private void showObjectHistogram() { | |
1341 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1342 ObjectHistogramCleanupThunk cleanup = | |
1343 new ObjectHistogramCleanupThunk(histo); | |
1344 doHeapIteration("Object Histogram", | |
1345 "Generating histogram...", | |
1346 histo, | |
1347 cleanup); | |
1348 } | |
1349 | |
1350 class ObjectHistogramCleanupThunk implements CleanupThunk { | |
1351 sun.jvm.hotspot.oops.ObjectHistogram histo; | |
1352 | |
1353 ObjectHistogramCleanupThunk(sun.jvm.hotspot.oops.ObjectHistogram histo) { | |
1354 this.histo = histo; | |
1355 } | |
1356 | |
1357 public void heapIterationComplete() { | |
1358 SwingUtilities.invokeLater(new Runnable() { | |
1359 public void run() { | |
1360 JInternalFrame histoFrame = new JInternalFrame("Object Histogram"); | |
1361 histoFrame.setResizable(true); | |
1362 histoFrame.setClosable(true); | |
1363 histoFrame.setIconifiable(true); | |
1364 histoFrame.getContentPane().setLayout(new BorderLayout()); | |
1365 ObjectHistogramPanel panel = new ObjectHistogramPanel(histo); | |
1366 panel.addPanelListener(HSDB.this); | |
1367 histoFrame.getContentPane().add(panel); | |
1368 desktop.add(histoFrame); | |
1369 GraphicsUtilities.reshapeToAspectRatio(histoFrame, 4.0f / 3.0f, 0.6f, | |
1370 histoFrame.getParent().getSize()); | |
1371 GraphicsUtilities.centerInContainer(histoFrame); | |
1372 histoFrame.show(); | |
1373 } | |
1374 }); | |
1375 } | |
1376 } | |
1377 | |
1378 public void showObjectsOfType(Klass type) { | |
1379 FindObjectByType finder = new FindObjectByType(type); | |
1380 FindObjectByTypeCleanupThunk cleanup = | |
1381 new FindObjectByTypeCleanupThunk(finder); | |
1382 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
1383 type.printValueOn(new PrintStream(bos)); | |
1384 String typeName = bos.toString(); | |
1385 doHeapIteration("Show Objects Of Type", | |
1386 "Finding instances of \"" + typeName + "\"", | |
1387 finder, | |
1388 cleanup); | |
1389 } | |
1390 | |
1391 class FindObjectByTypeCleanupThunk implements CleanupThunk { | |
1392 FindObjectByType finder; | |
1393 | |
1394 FindObjectByTypeCleanupThunk(FindObjectByType finder) { | |
1395 this.finder = finder; | |
1396 } | |
1397 | |
1398 public void heapIterationComplete() { | |
1399 SwingUtilities.invokeLater(new Runnable() { | |
1400 public void run() { | |
1401 JInternalFrame finderFrame = new JInternalFrame("Show Objects of Type"); | |
1402 finderFrame.getContentPane().setLayout(new BorderLayout()); | |
1403 finderFrame.setResizable(true); | |
1404 finderFrame.setClosable(true); | |
1405 finderFrame.setIconifiable(true); | |
1406 ObjectListPanel panel = new ObjectListPanel(finder.getResults(), | |
1407 new HeapProgress("Reverse Pointers Analysis")); | |
1408 panel.addPanelListener(HSDB.this); | |
1409 finderFrame.getContentPane().add(panel); | |
1410 desktop.add(finderFrame); | |
1411 GraphicsUtilities.reshapeToAspectRatio(finderFrame, 4.0f / 3.0f, 0.6f, | |
1412 finderFrame.getParent().getSize()); | |
1413 GraphicsUtilities.centerInContainer(finderFrame); | |
1414 finderFrame.show(); | |
1415 } | |
1416 }); | |
1417 } | |
1418 } | |
1419 | |
1420 private void showDebuggerConsole() { | |
1421 if (consoleFrame == null) { | |
1422 consoleFrame = new JInternalFrame("Debugger Console"); | |
1423 consoleFrame.setResizable(true); | |
1424 consoleFrame.setClosable(true); | |
1425 consoleFrame.setIconifiable(true); | |
1426 consoleFrame.getContentPane().setLayout(new BorderLayout()); | |
1427 consoleFrame.getContentPane().add(new DebuggerConsolePanel(agent.getDebugger()), BorderLayout.CENTER); | |
1428 GraphicsUtilities.reshapeToAspectRatio(consoleFrame, 5.0f, 0.9f, desktop.getSize()); | |
1429 } | |
1430 if (consoleFrame.getParent() == null) { | |
1431 desktop.add(consoleFrame); | |
1432 } | |
1433 consoleFrame.setVisible(true); | |
1434 consoleFrame.show(); | |
1435 consoleFrame.getContentPane().getComponent(0).requestFocus(); | |
1436 } | |
1437 | |
1438 private void showConsole() { | |
1439 CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() { | |
1440 public HotSpotAgent getAgent() { | |
1441 return agent; | |
1442 } | |
1443 public boolean isAttached() { | |
1444 return attached; | |
1445 } | |
1446 public void attach(String pid) { | |
1447 attach(pid); | |
1448 } | |
1449 public void attach(String java, String core) { | |
1450 } | |
1451 public void detach() { | |
1452 detachDebugger(); | |
1453 } | |
1454 public void reattach() { | |
1455 if (attached) { | |
1456 detachDebugger(); | |
1457 } | |
1458 if (pidText != null) { | |
1459 attach(pidText); | |
1460 } else { | |
1461 attach(execPath, coreFilename); | |
1462 } | |
1463 } | |
1464 }; | |
1465 | |
1466 showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null))); | |
1467 } | |
1468 | |
1469 private void showFindByQueryPanel() { | |
1470 showPanel("Find Object by Query", new FindByQueryPanel()); | |
1471 } | |
1472 | |
1473 private void showFindPanel() { | |
1474 showPanel("Find Pointer", new FindPanel()); | |
1475 } | |
1476 | |
1477 private void showFindInHeapPanel() { | |
1478 showPanel("Find Address In Heap", new FindInHeapPanel()); | |
1479 } | |
1480 | |
1481 private void showFindInCodeCachePanel() { | |
1482 showPanel("Find Address In Code Cache", new FindInCodeCachePanel()); | |
1483 } | |
1484 | |
1485 private void showHeapParametersPanel() { | |
1486 showPanel("Heap Parameters", new HeapParametersPanel()); | |
1487 } | |
1488 | |
1489 public void showThreadInfo(final JavaThread thread) { | |
1490 showPanel("Info for " + thread.getThreadName(), new ThreadInfoPanel(thread)); | |
1491 } | |
1492 | |
1493 public void showJavaStackTrace(final JavaThread thread) { | |
1494 JavaStackTracePanel jstp = new JavaStackTracePanel(); | |
1495 showPanel("Java stack trace for " + thread.getThreadName(), jstp); | |
1496 jstp.setJavaThread(thread); | |
1497 } | |
1498 | |
1499 private void showDeadlockDetectionPanel() { | |
1500 showPanel("Deadlock Detection", new DeadlockDetectionPanel()); | |
1501 } | |
1502 | |
1503 private void showMonitorCacheDumpPanel() { | |
1504 showPanel("Monitor Cache Dump", new MonitorCacheDumpPanel()); | |
1505 } | |
1506 | |
1507 public void showClassBrowser() { | |
1508 final JInternalFrame progressFrame = new JInternalFrame("Class Browser"); | |
1509 progressFrame.setResizable(true); | |
1510 progressFrame.setClosable(true); | |
1511 progressFrame.setIconifiable(true); | |
1512 progressFrame.getContentPane().setLayout(new BorderLayout()); | |
1513 final ProgressBarPanel bar = new ProgressBarPanel("Generating class list .."); | |
1514 bar.setIndeterminate(true); | |
1515 progressFrame.getContentPane().add(bar, BorderLayout.CENTER); | |
1516 desktop.add(progressFrame); | |
1517 progressFrame.pack(); | |
1518 GraphicsUtilities.centerInContainer(progressFrame); | |
1519 progressFrame.show(); | |
1520 | |
1521 workerThread.invokeLater(new Runnable() { | |
1522 public void run() { | |
1523 HTMLGenerator htmlGen = new HTMLGenerator(); | |
1524 InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses(); | |
1525 final String htmlText = htmlGen.genHTMLForKlassNames(klasses); | |
1526 SwingUtilities.invokeLater(new Runnable() { | |
1527 public void run() { | |
1528 JInternalFrame cbFrame = new JInternalFrame("Class Browser"); | |
1529 cbFrame.getContentPane().setLayout(new BorderLayout()); | |
1530 cbFrame.setResizable(true); | |
1531 cbFrame.setClosable(true); | |
1532 cbFrame.setIconifiable(true); | |
1533 ClassBrowserPanel cbPanel = new ClassBrowserPanel(); | |
1534 cbFrame.getContentPane().add(cbPanel, BorderLayout.CENTER); | |
1535 desktop.remove(progressFrame); | |
1536 desktop.repaint(); | |
1537 desktop.add(cbFrame); | |
1538 GraphicsUtilities.reshapeToAspectRatio(cbFrame, 1.25f, 0.85f, | |
1539 cbFrame.getParent().getSize()); | |
1540 cbFrame.show(); | |
1541 cbPanel.setClassesText(htmlText); | |
1542 } | |
1543 }); | |
1544 } | |
1545 }); | |
1546 } | |
1547 | |
1548 public void showCodeViewer() { | |
1549 showPanel("Code Viewer", new CodeViewerPanel(), 1.25f, 0.85f); | |
1550 } | |
1551 | |
1552 public void showCodeViewer(final Address address) { | |
1553 final CodeViewerPanel panel = new CodeViewerPanel(); | |
1554 showPanel("Code Viewer", panel, 1.25f, 0.85f); | |
1555 SwingUtilities.invokeLater(new Runnable() { | |
1556 public void run() { | |
1557 panel.viewAddress(address); | |
1558 } | |
1559 }); | |
1560 | |
1561 } | |
1562 | |
1563 public void showMemoryViewer() { | |
1564 showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8)); | |
1565 } | |
1566 | |
1567 public void showCommandLineFlags() { | |
1568 showPanel("Command Line Flags", new VMFlagsPanel()); | |
1569 } | |
1570 | |
1571 public void showVMVersion() { | |
1572 showPanel("VM Version Info", new VMVersionInfoPanel()); | |
1573 } | |
1574 | |
1575 public void showSystemProperties() { | |
1576 showPanel("System Properties", new SysPropsPanel()); | |
1577 } | |
1578 | |
1579 private void showPanel(String name, JPanel panel) { | |
1580 showPanel(name, panel, 5.0f / 3.0f, 0.4f); | |
1581 } | |
1582 | |
1583 private void showPanel(String name, JPanel panel, float aspectRatio, float fillRatio) { | |
1584 JInternalFrame frame = new JInternalFrame(name); | |
1585 frame.getContentPane().setLayout(new BorderLayout()); | |
1586 frame.setResizable(true); | |
1587 frame.setClosable(true); | |
1588 frame.setIconifiable(true); | |
1589 frame.setMaximizable(true); | |
1590 frame.getContentPane().add(panel, BorderLayout.CENTER); | |
1591 desktop.add(frame); | |
1592 GraphicsUtilities.reshapeToAspectRatio(frame, aspectRatio, fillRatio, frame.getParent().getSize()); | |
1593 GraphicsUtilities.randomLocation(frame); | |
1594 frame.show(); | |
1595 if (panel instanceof SAPanel) { | |
1596 ((SAPanel)panel).addPanelListener(this); | |
1597 } | |
1598 } | |
1599 | |
1600 //-------------------------------------------------------------------------------- | |
1601 // Framework for heap iteration with progress bar | |
1602 // | |
1603 | |
1604 interface CleanupThunk { | |
1605 public void heapIterationComplete(); | |
1606 } | |
1607 | |
1608 class HeapProgress implements HeapProgressThunk { | |
1609 private JInternalFrame frame; | |
1610 private ProgressBarPanel bar; | |
1611 private String windowTitle; | |
1612 private String progressBarTitle; | |
1613 private CleanupThunk cleanup; | |
1614 | |
1615 HeapProgress(String windowTitle) { | |
1616 this(windowTitle, "Percentage of heap visited", null); | |
1617 } | |
1618 | |
1619 HeapProgress(String windowTitle, String progressBarTitle) { | |
1620 this(windowTitle, progressBarTitle, null); | |
1621 } | |
1622 | |
1623 HeapProgress(String windowTitle, String progressBarTitle, CleanupThunk cleanup) { | |
1624 this.windowTitle = windowTitle; | |
1625 this.progressBarTitle = progressBarTitle; | |
1626 this.cleanup = cleanup; | |
1627 } | |
1628 | |
1629 public void heapIterationFractionUpdate(final double fractionOfHeapVisited) { | |
1630 if (frame == null) { | |
1631 SwingUtilities.invokeLater(new Runnable() { | |
1632 public void run() { | |
1633 frame = new JInternalFrame(windowTitle); | |
1634 frame.setResizable(true); | |
1635 frame.setIconifiable(true); | |
1636 frame.getContentPane().setLayout(new BorderLayout()); | |
1637 bar = new ProgressBarPanel(progressBarTitle); | |
1638 frame.getContentPane().add(bar, BorderLayout.CENTER); | |
1639 desktop.add(frame); | |
1640 frame.pack(); | |
1641 GraphicsUtilities.constrainToSize(frame, frame.getParent().getSize()); | |
1642 GraphicsUtilities.centerInContainer(frame); | |
1643 frame.show(); | |
1644 } | |
1645 }); | |
1646 } | |
1647 | |
1648 SwingUtilities.invokeLater(new Runnable() { | |
1649 public void run() { | |
1650 bar.setValue(fractionOfHeapVisited); | |
1651 } | |
1652 }); | |
1653 } | |
1654 | |
1655 public void heapIterationComplete() { | |
1656 SwingUtilities.invokeLater(new Runnable() { | |
1657 public void run() { | |
1658 desktop.remove(frame); | |
1659 desktop.repaint(); | |
1660 if (VM.getVM().getRevPtrs() != null) { | |
1661 // Ended up computing reverse pointers as a side-effect | |
1662 computeRevPtrsMenuItem.setEnabled(false); | |
1663 } | |
1664 } | |
1665 }); | |
1666 | |
1667 if (cleanup != null) { | |
1668 cleanup.heapIterationComplete(); | |
1669 } | |
1670 } | |
1671 } | |
1672 | |
1673 class VisitHeap implements Runnable { | |
1674 HeapVisitor visitor; | |
1675 | |
1676 VisitHeap(HeapVisitor visitor) { | |
1677 this.visitor = visitor; | |
1678 } | |
1679 | |
1680 public void run() { | |
1681 VM.getVM().getObjectHeap().iterate(visitor); | |
1682 } | |
1683 } | |
1684 | |
1685 private void doHeapIteration(String frameTitle, | |
1686 String progressBarText, | |
1687 HeapVisitor visitor, | |
1688 CleanupThunk cleanup) { | |
1689 sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram(); | |
1690 HeapProgress progress = new HeapProgress(frameTitle, | |
1691 progressBarText, | |
1692 cleanup); | |
1693 HeapVisitor progVisitor = new ProgressiveHeapVisitor(visitor, progress); | |
1694 workerThread.invokeLater(new VisitHeap(progVisitor)); | |
1695 } | |
1696 | |
1697 //-------------------------------------------------------------------------------- | |
1698 // Stack trace helper | |
1699 // | |
1700 | |
1701 private static JavaVFrame getLastJavaVFrame(JavaThread cur) { | |
1702 RegisterMap regMap = cur.newRegisterMap(true); | |
1703 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1704 if (f == null) return null; | |
1705 boolean imprecise = true; | |
1706 if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) { | |
1707 System.err.println("Correcting for invalid interpreter frame"); | |
1708 f = f.sender(regMap); | |
1709 imprecise = false; | |
1710 } | |
1711 VFrame vf = VFrame.newVFrame(f, regMap, cur, true, imprecise); | |
1712 if (vf == null) { | |
1713 System.err.println(" (Unable to create vframe for topmost frame guess)"); | |
1714 return null; | |
1715 } | |
1716 if (vf.isJavaFrame()) { | |
1717 return (JavaVFrame) vf; | |
1718 } | |
1719 return (JavaVFrame) vf.javaSender(); | |
1720 } | |
1721 | |
1722 // Internal routine for debugging | |
1723 private static void dumpStack(JavaThread cur) { | |
1724 RegisterMap regMap = cur.newRegisterMap(true); | |
1725 sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess(); | |
1726 PrintStream tty = System.err; | |
1727 while (f != null) { | |
1728 tty.print("Found "); | |
1729 if (f.isInterpretedFrame()) { tty.print("interpreted"); } | |
1730 else if (f.isCompiledFrame()) { tty.print("compiled"); } | |
1731 else if (f.isEntryFrame()) { tty.print("entry"); } | |
1732 else if (f.isNativeFrame()) { tty.print("native"); } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
1733 else if (f.isRuntimeFrame()) { tty.print("runtime"); } |
0 | 1734 else { tty.print("external"); } |
1735 tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP()); | |
1736 if (f.isSignalHandlerFrameDbg()) { | |
1737 tty.print(" (SIGNAL HANDLER)"); | |
1738 } | |
1739 tty.println(); | |
1740 | |
1741 if (!f.isFirstFrame()) { | |
1742 f = f.sender(regMap); | |
1743 } else { | |
1744 f = null; | |
1745 } | |
1746 } | |
1747 } | |
1748 | |
1749 //-------------------------------------------------------------------------------- | |
1750 // Component utilities | |
1751 // | |
1752 | |
1753 private static JMenuItem createMenuItem(String name, ActionListener l) { | |
1754 JMenuItem item = new JMenuItem(name); | |
1755 item.addActionListener(l); | |
1756 return item; | |
1757 } | |
1758 | |
1759 /** Punctuates the given string with \n's where necessary to not | |
1760 exceed the given number of characters per line. Strips | |
1761 extraneous whitespace. */ | |
1762 private String formatMessage(String message, int charsPerLine) { | |
1763 StringBuffer buf = new StringBuffer(message.length()); | |
1764 StringTokenizer tokenizer = new StringTokenizer(message); | |
1765 int curLineLength = 0; | |
1766 while (tokenizer.hasMoreTokens()) { | |
1767 String tok = tokenizer.nextToken(); | |
1768 if (curLineLength + tok.length() > charsPerLine) { | |
1769 buf.append('\n'); | |
1770 curLineLength = 0; | |
1771 } else { | |
1772 if (curLineLength != 0) { | |
1773 buf.append(' '); | |
1774 ++curLineLength; | |
1775 } | |
1776 } | |
1777 buf.append(tok); | |
1778 curLineLength += tok.length(); | |
1779 } | |
1780 return buf.toString(); | |
1781 } | |
1782 | |
1783 private void setMenuItemsEnabled(java.util.List items, boolean enabled) { | |
1784 for (Iterator iter = items.iterator(); iter.hasNext(); ) { | |
1785 ((JMenuItem) iter.next()).setEnabled(enabled); | |
1786 } | |
1787 } | |
1788 } |