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