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