Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java
41159 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot;2526import java.io.*;27import java.awt.*;28import java.awt.event.*;29import javax.swing.*;30import java.util.*;3132import sun.jvm.hotspot.code.*;33import sun.jvm.hotspot.compiler.*;34import sun.jvm.hotspot.debugger.*;35import sun.jvm.hotspot.gc.epsilon.*;36import sun.jvm.hotspot.gc.parallel.*;37import sun.jvm.hotspot.gc.shared.*;38import sun.jvm.hotspot.gc.shenandoah.*;39import sun.jvm.hotspot.gc.g1.*;40import sun.jvm.hotspot.gc.z.*;41import sun.jvm.hotspot.interpreter.*;42import sun.jvm.hotspot.memory.*;43import sun.jvm.hotspot.oops.*;44import sun.jvm.hotspot.runtime.*;45import sun.jvm.hotspot.ui.*;46import sun.jvm.hotspot.ui.tree.*;47import sun.jvm.hotspot.ui.classbrowser.*;48import sun.jvm.hotspot.utilities.*;49import sun.jvm.hotspot.utilities.Observable;50import sun.jvm.hotspot.utilities.Observer;5152/** The top-level HotSpot Debugger. FIXME: make this an embeddable53component! (Among other things, figure out what to do with the54menu bar...) */5556public class HSDB implements ObjectHistogramPanel.Listener, SAListener {57public static void main(String[] args) {58new HSDB(args).run();59}6061//--------------------------------------------------------------------------------62// Internals only below this point63//64private HotSpotAgent agent;65private JVMDebugger jvmDebugger;66private JDesktopPane desktop;67private boolean attached;68private boolean argError;69private JFrame frame;70private java.util.List<JMenuItem> attachMenuItems;71private java.util.List<JMenuItem> detachMenuItems;72private JMenu toolsMenu;73private JMenuItem showDbgConsoleMenuItem;74private JMenuItem computeRevPtrsMenuItem;75private JInternalFrame attachWaitDialog;76private JInternalFrame threadsFrame;77private JInternalFrame consoleFrame;78private WorkerThread workerThread;79// These had to be made data members because they are referenced in inner classes.80private int pid;81private String execPath;82private String coreFilename;83private String debugServerName;8485private void doUsage() {86System.out.println("Usage: java HSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]");87System.out.println(" pid: attach to the process whose id is 'pid'");88System.out.println(" path-to-java-executable: Debug a core file produced by this program");89System.out.println(" path-to-corefile: Debug this corefile. The default is 'core'");90System.out.println(" If no arguments are specified, you can select what to do from the GUI.\n");91HotSpotAgent.showUsage();92argError = true;93}9495public HSDB(JVMDebugger d) {96pid = -1;97execPath = null;98coreFilename = null;99debugServerName = null;100jvmDebugger = d;101}102103private HSDB(String[] args) {104pid = -1;105execPath = null;106coreFilename = null;107debugServerName = null;108109switch (args.length) {110case (0):111break;112113case (1):114if (args[0].equals("help") || args[0].equals("-help")) {115doUsage();116}117try {118// Attempt to attach as a PID119pid = Integer.parseInt(args[0]);120} catch (NumberFormatException e) {121// Attempt to connect to remote debug server122debugServerName = args[0];123}124break;125126case (2):127execPath = args[0];128coreFilename = args[1];129break;130131default:132System.out.println("HSDB Error: Too many options specified");133doUsage();134}135}136137private class CloseUI extends WindowAdapter {138139@Override140public void windowClosing(WindowEvent e) {141workerThread.shutdown();142frame.dispose();143}144145}146147public void run() {148// Don't start the UI if there were bad arguments.149if (argError) {150return;151}152153// Create frame first, to catch any GUI creation issues154// before we initialize agent155156frame = new JFrame("HSDB - HotSpot Debugger");157frame.setSize(800, 600);158frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);159frame.addWindowListener(new CloseUI());160161agent = new HotSpotAgent();162workerThread = new WorkerThread();163attachMenuItems = new java.util.ArrayList<>();164detachMenuItems = new java.util.ArrayList<>();165166167JMenuBar menuBar = new JMenuBar();168169//170// File menu171//172173JMenu menu = new JMenu("File");174menu.setMnemonic(KeyEvent.VK_F);175JMenuItem item;176item = createMenuItem("Attach to HotSpot process...",177new ActionListener() {178public void actionPerformed(ActionEvent e) {179showAttachDialog();180}181});182item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));183item.setMnemonic(KeyEvent.VK_A);184menu.add(item);185attachMenuItems.add(item);186187item = createMenuItem("Open HotSpot core file...",188new ActionListener() {189public void actionPerformed(ActionEvent e) {190showOpenCoreFileDialog();191}192});193item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK));194item.setMnemonic(KeyEvent.VK_O);195menu.add(item);196attachMenuItems.add(item);197198item = createMenuItem("Connect to debug server...",199new ActionListener() {200public void actionPerformed(ActionEvent e) {201showConnectDialog();202}203});204item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.ALT_MASK));205item.setMnemonic(KeyEvent.VK_S);206menu.add(item);207attachMenuItems.add(item);208209item = createMenuItem("Detach",210new ActionListener() {211public void actionPerformed(ActionEvent e) {212detach();213}214});215item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));216item.setMnemonic(KeyEvent.VK_S);217menu.add(item);218detachMenuItems.add(item);219220// Disable detach menu items at first221setMenuItemsEnabled(detachMenuItems, false);222223menu.addSeparator();224225item = createMenuItem("Exit",226new ActionListener() {227public void actionPerformed(ActionEvent e) {228workerThread.shutdown();229frame.dispose();230}231});232item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));233item.setMnemonic(KeyEvent.VK_X);234menu.add(item);235menuBar.add(menu);236237//238// Tools menu239//240241toolsMenu = new JMenu("Tools");242toolsMenu.setMnemonic(KeyEvent.VK_T);243244item = createMenuItem("Class Browser",245new ActionListener() {246public void actionPerformed(ActionEvent e) {247showClassBrowser();248}249});250item.setMnemonic(KeyEvent.VK_B);251252toolsMenu.add(item);253254item = createMenuItem("Code Viewer",255new ActionListener() {256public void actionPerformed(ActionEvent e) {257showCodeViewer();258}259});260item.setMnemonic(KeyEvent.VK_C);261262toolsMenu.add(item);263264265item = createMenuItem("Compute Reverse Ptrs",266new ActionListener() {267public void actionPerformed(ActionEvent e) {268fireComputeReversePtrs();269}270});271computeRevPtrsMenuItem = item;272item.setMnemonic(KeyEvent.VK_M);273toolsMenu.add(item);274275item = createMenuItem("Deadlock Detection",276new ActionListener() {277public void actionPerformed(ActionEvent e) {278showDeadlockDetectionPanel();279}280});281item.setMnemonic(KeyEvent.VK_D);282toolsMenu.add(item);283284285item = createMenuItem("Find Pointer",286new ActionListener() {287public void actionPerformed(ActionEvent e) {288showFindPanel();289}290});291item.setMnemonic(KeyEvent.VK_P);292toolsMenu.add(item);293294item = createMenuItem("Find Value In Heap",295new ActionListener() {296public void actionPerformed(ActionEvent e) {297showFindInHeapPanel();298}299});300item.setMnemonic(KeyEvent.VK_V);301toolsMenu.add(item);302303item = createMenuItem("Find Value In Code Cache",304new ActionListener() {305public void actionPerformed(ActionEvent e) {306showFindInCodeCachePanel();307}308});309item.setMnemonic(KeyEvent.VK_A);310toolsMenu.add(item);311312item = createMenuItem("Heap Parameters",313new ActionListener() {314public void actionPerformed(ActionEvent e) {315showHeapParametersPanel();316}317});318item.setMnemonic(KeyEvent.VK_H);319toolsMenu.add(item);320321item = createMenuItem("Inspector",322new ActionListener() {323public void actionPerformed(ActionEvent e) {324showInspector(null);325}326});327item.setMnemonic(KeyEvent.VK_R);328item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK));329toolsMenu.add(item);330331item = createMenuItem("Memory Viewer",332new ActionListener() {333public void actionPerformed(ActionEvent e) {334showMemoryViewer();335}336});337item.setMnemonic(KeyEvent.VK_M);338toolsMenu.add(item);339340item = createMenuItem("Monitor Cache Dump",341new ActionListener() {342public void actionPerformed(ActionEvent e) {343showMonitorCacheDumpPanel();344}345});346item.setMnemonic(KeyEvent.VK_D);347toolsMenu.add(item);348349item = createMenuItem("Object Histogram",350new ActionListener() {351public void actionPerformed(ActionEvent e) {352showObjectHistogram();353}354});355item.setMnemonic(KeyEvent.VK_O);356toolsMenu.add(item);357358item = createMenuItem("Show System Properties",359new ActionListener() {360public void actionPerformed(ActionEvent e) {361showSystemProperties();362}363});364item.setMnemonic(KeyEvent.VK_S);365toolsMenu.add(item);366367item = createMenuItem("Show VM Version",368new ActionListener() {369public void actionPerformed(ActionEvent e) {370showVMVersion();371}372});373item.setMnemonic(KeyEvent.VK_M);374toolsMenu.add(item);375376item = createMenuItem("Show -XX flags",377new ActionListener() {378public void actionPerformed(ActionEvent e) {379showCommandLineFlags();380}381});382item.setMnemonic(KeyEvent.VK_X);383toolsMenu.add(item);384385toolsMenu.setEnabled(false);386menuBar.add(toolsMenu);387388//389// Windows menu390//391392JMenu windowsMenu = new JMenu("Windows");393windowsMenu.setMnemonic(KeyEvent.VK_W);394item = createMenuItem("Console",395new ActionListener() {396public void actionPerformed(ActionEvent e) {397showConsole();398}399});400item.setMnemonic(KeyEvent.VK_C);401windowsMenu.add(item);402showDbgConsoleMenuItem = createMenuItem("Debugger Console",403new ActionListener() {404public void actionPerformed(ActionEvent e) {405showDebuggerConsole();406}407});408showDbgConsoleMenuItem.setMnemonic(KeyEvent.VK_D);409windowsMenu.add(showDbgConsoleMenuItem);410showDbgConsoleMenuItem.setEnabled(false);411412menuBar.add(windowsMenu);413414415frame.setJMenuBar(menuBar);416417desktop = new JDesktopPane();418frame.getContentPane().add(desktop);419GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize());420GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize());421frame.setVisible(true);422423Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {424public void run() {425detachDebugger();426}427});428429// If jvmDebugger is already set, we have been given a JVMDebugger.430// Otherwise, if pid != -1 we are supposed to attach to it.431// If execPath != null, it is the path of a jdk/bin/java432// and coreFilename is the pathname of a core file we are433// supposed to attach to.434// Finally, if debugServerName != null, we are supposed to435// connect to remote debug server.436437if (jvmDebugger != null) {438attach(jvmDebugger);439} else if (pid != -1) {440attach(pid);441} else if (execPath != null) {442attach(execPath, coreFilename);443} else if (debugServerName != null) {444connect(debugServerName);445}446}447448// FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog449private void showAttachDialog() {450// FIXME: create filtered text field which only accepts numbers451setMenuItemsEnabled(attachMenuItems, false);452final JInternalFrame attachDialog = new JInternalFrame("Attach to HotSpot process");453attachDialog.getContentPane().setLayout(new BorderLayout());454455JPanel panel = new JPanel();456panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));457panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));458attachDialog.setBackground(panel.getBackground());459460panel.add(new JLabel("Enter process ID:"));461final JTextField pidTextField = new JTextField(10);462ActionListener attacher = new ActionListener() {463public void actionPerformed(ActionEvent e) {464attachDialog.setVisible(false);465desktop.remove(attachDialog);466workerThread.invokeLater(new Runnable() {467public void run() {468attach(Integer.parseInt(pidTextField.getText()));469}470});471}472};473474pidTextField.addActionListener(attacher);475panel.add(pidTextField);476attachDialog.getContentPane().add(panel, BorderLayout.NORTH);477478Box vbox = Box.createVerticalBox();479panel = new JPanel();480panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));481panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));482JTextArea ta = new JTextArea(483"Enter the process ID of a currently-running HotSpot process. On " +484"most Unix operating systems, this can be determined by " +485"typing \"ps -u <your username> | grep java\"; the process ID is the " +486"first number which appears on the resulting line. On Windows, the " +487"process ID is present in the Task Manager, which can be brought up " +488"while logged on to the desktop by pressing Ctrl-Alt-Delete.");489ta.setLineWrap(true);490ta.setWrapStyleWord(true);491ta.setEditable(false);492ta.setBackground(panel.getBackground());493panel.add(ta);494vbox.add(panel);495496Box hbox = Box.createHorizontalBox();497hbox.add(Box.createGlue());498JButton button = new JButton("OK");499button.addActionListener(attacher);500hbox.add(button);501hbox.add(Box.createHorizontalStrut(20));502button = new JButton("Cancel");503button.addActionListener(new ActionListener() {504public void actionPerformed(ActionEvent e) {505attachDialog.setVisible(false);506desktop.remove(attachDialog);507setMenuItemsEnabled(attachMenuItems, true);508}509});510hbox.add(button);511hbox.add(Box.createGlue());512panel = new JPanel();513panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));514panel.add(hbox);515vbox.add(panel);516517attachDialog.getContentPane().add(vbox, BorderLayout.SOUTH);518519desktop.add(attachDialog);520attachDialog.setSize(400, 300);521GraphicsUtilities.centerInContainer(attachDialog);522attachDialog.show();523pidTextField.requestFocus();524}525526// FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog527private void showOpenCoreFileDialog() {528setMenuItemsEnabled(attachMenuItems, false);529final JInternalFrame dialog = new JInternalFrame("Open Core File");530dialog.getContentPane().setLayout(new BorderLayout());531532JPanel panel = new JPanel();533panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));534panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));535dialog.setBackground(panel.getBackground());536537Box hbox = Box.createHorizontalBox();538Box vbox = Box.createVerticalBox();539vbox.add(new JLabel("Path to core file:"));540vbox.add(new JLabel("Path to Java executable:"));541hbox.add(vbox);542543vbox = Box.createVerticalBox();544final JTextField corePathField = new JTextField(40);545final JTextField execPathField = new JTextField(40);546vbox.add(corePathField);547vbox.add(execPathField);548hbox.add(vbox);549550final JButton browseCorePath = new JButton("Browse ..");551final JButton browseExecPath = new JButton("Browse ..");552browseCorePath.addActionListener(new ActionListener() {553public void actionPerformed(ActionEvent e) {554JFileChooser fileChooser = new JFileChooser(new File("."));555int retVal = fileChooser.showOpenDialog(dialog);556if (retVal == JFileChooser.APPROVE_OPTION) {557corePathField.setText(fileChooser.getSelectedFile().getPath());558}559}560});561browseExecPath.addActionListener(new ActionListener() {562public void actionPerformed(ActionEvent e) {563JFileChooser fileChooser = new JFileChooser(new File("."));564int retVal = fileChooser.showOpenDialog(dialog);565if (retVal == JFileChooser.APPROVE_OPTION) {566execPathField.setText(fileChooser.getSelectedFile().getPath());567}568}569});570vbox = Box.createVerticalBox();571vbox.add(browseCorePath);572vbox.add(browseExecPath);573hbox.add(vbox);574575panel.add(hbox);576dialog.getContentPane().add(panel, BorderLayout.NORTH);577578ActionListener attacher = new ActionListener() {579public void actionPerformed(ActionEvent e) {580dialog.setVisible(false);581desktop.remove(dialog);582workerThread.invokeLater(new Runnable() {583public void run() {584attach(execPathField.getText(), corePathField.getText());585}586});587}588};589corePathField.addActionListener(attacher);590execPathField.addActionListener(attacher);591592vbox = Box.createVerticalBox();593panel = new JPanel();594panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));595panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));596JTextArea ta = new JTextArea(597"Enter the full path names to the core file from a HotSpot process " +598"and the Java executable from which it came. The latter is typically " +599"located in the JDK/JRE directory under the directory " +600"jre/bin/<arch>/native_threads.");601ta.setLineWrap(true);602ta.setWrapStyleWord(true);603ta.setEditable(false);604ta.setBackground(panel.getBackground());605panel.add(ta);606vbox.add(panel);607608hbox = Box.createHorizontalBox();609hbox.add(Box.createGlue());610JButton button = new JButton("OK");611button.addActionListener(attacher);612hbox.add(button);613hbox.add(Box.createHorizontalStrut(20));614button = new JButton("Cancel");615button.addActionListener(new ActionListener() {616public void actionPerformed(ActionEvent e) {617dialog.setVisible(false);618desktop.remove(dialog);619setMenuItemsEnabled(attachMenuItems, true);620}621});622hbox.add(button);623hbox.add(Box.createGlue());624panel = new JPanel();625panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));626panel.add(hbox);627vbox.add(panel);628629dialog.getContentPane().add(vbox, BorderLayout.SOUTH);630631desktop.add(dialog);632dialog.setSize(500, 300);633GraphicsUtilities.centerInContainer(dialog);634dialog.show();635corePathField.requestFocus();636}637638// FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog639private void showConnectDialog() {640// FIXME: create filtered text field which only accepts numbers641setMenuItemsEnabled(attachMenuItems, false);642final JInternalFrame dialog = new JInternalFrame("Connect to HotSpot Debug Server");643dialog.getContentPane().setLayout(new BorderLayout());644645JPanel panel = new JPanel();646panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));647panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));648dialog.setBackground(panel.getBackground());649650panel.add(new JLabel("Enter machine name:"));651final JTextField pidTextField = new JTextField(40);652ActionListener attacher = new ActionListener() {653public void actionPerformed(ActionEvent e) {654dialog.setVisible(false);655desktop.remove(dialog);656workerThread.invokeLater(new Runnable() {657public void run() {658connect(pidTextField.getText());659}660});661}662};663664pidTextField.addActionListener(attacher);665panel.add(pidTextField);666dialog.getContentPane().add(panel, BorderLayout.NORTH);667668Box vbox = Box.createVerticalBox();669panel = new JPanel();670panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));671panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));672JTextArea ta = new JTextArea(673"Enter the name of a machine on which the HotSpot \"Debug Server\" is " +674"running and is attached to a process or core file.");675ta.setLineWrap(true);676ta.setWrapStyleWord(true);677ta.setEditable(false);678ta.setBackground(panel.getBackground());679panel.add(ta);680vbox.add(panel);681682Box hbox = Box.createHorizontalBox();683hbox.add(Box.createGlue());684JButton button = new JButton("OK");685button.addActionListener(attacher);686hbox.add(button);687hbox.add(Box.createHorizontalStrut(20));688button = new JButton("Cancel");689button.addActionListener(new ActionListener() {690public void actionPerformed(ActionEvent e) {691dialog.setVisible(false);692desktop.remove(dialog);693setMenuItemsEnabled(attachMenuItems, true);694}695});696hbox.add(button);697hbox.add(Box.createGlue());698panel = new JPanel();699panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));700panel.add(hbox);701vbox.add(panel);702703dialog.getContentPane().add(vbox, BorderLayout.SOUTH);704705desktop.add(dialog);706dialog.setSize(400, 300);707GraphicsUtilities.centerInContainer(dialog);708dialog.show();709pidTextField.requestFocus();710}711712public void showThreadOopInspector(JavaThread thread) {713showInspector(new OopTreeNodeAdapter(thread.getThreadObj(), null));714}715716public void showInspector(SimpleTreeNode adapter) {717showPanel("Inspector", new Inspector(adapter), 1.0f, 0.65f);718}719720public void showLiveness(Oop oop, LivenessPathList liveness) {721ByteArrayOutputStream bos = new ByteArrayOutputStream();722PrintStream tty = new PrintStream(bos);723int numPaths = liveness.size();724for (int i = 0; i < numPaths; i++) {725tty.println("Path " + (i + 1) + " of " + numPaths + ":");726liveness.get(i).printOn(tty);727}728JTextArea ta = new JTextArea(bos.toString());729ta.setLineWrap(true);730ta.setWrapStyleWord(true);731ta.setEditable(false);732733JPanel panel = new JPanel();734panel.setLayout(new BorderLayout());735736JScrollPane scroller = new JScrollPane();737scroller.getViewport().add(ta);738739panel.add(scroller, BorderLayout.CENTER);740741bos = new ByteArrayOutputStream();742tty = new PrintStream(bos);743tty.print("Liveness result for ");744Oop.printOopValueOn(oop, tty);745746JInternalFrame frame = new JInternalFrame(bos.toString());747frame.setResizable(true);748frame.setClosable(true);749frame.setIconifiable(true);750frame.getContentPane().setLayout(new BorderLayout());751frame.getContentPane().add(panel, BorderLayout.CENTER);752frame.pack();753desktop.add(frame);754GraphicsUtilities.reshapeToAspectRatio(frame, 0.5f / 0.2f, 0.5f, frame.getParent().getSize());755frame.show();756}757758private void fireComputeReversePtrs() {759// Possible this might have been computed elsewhere760if (VM.getVM().getRevPtrs() != null) {761computeRevPtrsMenuItem.setEnabled(false);762return;763}764765workerThread.invokeLater(new Runnable() {766public void run() {767HeapProgress progress = new HeapProgress("Reverse Pointers Analysis");768try {769ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();770analysis.setHeapProgressThunk(progress);771analysis.run();772computeRevPtrsMenuItem.setEnabled(false);773} catch (OutOfMemoryError e) {774final String errMsg = formatMessage(e.toString(), 80);775SwingUtilities.invokeLater(new Runnable() {776public void run() {777JOptionPane.showInternalMessageDialog(desktop,778"Error computing reverse pointers:" + errMsg,779"Error",780JOptionPane.WARNING_MESSAGE);781}782});783} finally {784// make sure the progress bar goes away785progress.heapIterationComplete();786}787}788});789}790791// Simple struct containing signal information792class SignalInfo {793public int sigNum;794public String sigName;795}796797// Need to have mutable vframe as well as visible memory panel798abstract class StackWalker implements Runnable {799protected JavaVFrame vf;800protected AnnotatedMemoryPanel annoPanel;801802StackWalker(JavaVFrame vf, AnnotatedMemoryPanel annoPanel) {803this.vf = vf;804this.annoPanel = annoPanel;805}806}807808public void showThreadStackMemory(final JavaThread thread) {809// dumpStack(thread);810JavaVFrame vframe = getLastJavaVFrame(thread);811if (vframe == null) {812JOptionPane.showInternalMessageDialog(desktop,813"Thread \"" + thread.getThreadName() +814"\" has no Java frames on its stack",815"Show Stack Memory",816JOptionPane.INFORMATION_MESSAGE);817return;818}819820JInternalFrame stackFrame = new JInternalFrame("Stack Memory for " + thread.getThreadName());821stackFrame.getContentPane().setLayout(new BorderLayout());822stackFrame.setResizable(true);823stackFrame.setClosable(true);824stackFrame.setIconifiable(true);825final long addressSize = agent.getTypeDataBase().getAddressSize();826boolean is64Bit = (addressSize == 8);827// This is somewhat of a hack to guess a thread's stack limits since the828// JavaThread doesn't support this functionality. However it is nice in that829// it locks us into the active region of the thread's stack and not its830// theoretical limits.831//832sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess();833Address sp = tmpFrame.getSP();834Address starting = sp;835Address maxSP = starting;836Address minSP = starting;837RegisterMap tmpMap = thread.newRegisterMap(false);838while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {839tmpFrame = tmpFrame.sender(tmpMap);840if (tmpFrame != null) {841sp = tmpFrame.getSP();842if (sp != null) {843maxSP = AddressOps.max(maxSP, sp);844minSP = AddressOps.min(minSP, sp);845}846}847848}849// It is useful to be able to see say +/- 8K on the current stack range850AnnotatedMemoryPanel annoMemPanel = new AnnotatedMemoryPanel(agent.getDebugger(), is64Bit, starting,851minSP.addOffsetTo(-8192),852maxSP.addOffsetTo( 8192));853854stackFrame.getContentPane().add(annoMemPanel, BorderLayout.CENTER);855desktop.add(stackFrame);856GraphicsUtilities.reshapeToAspectRatio(stackFrame, 4.0f / 3.0f, 0.85f, stackFrame.getParent().getSize());857stackFrame.show();858859// Stackmap computation for interpreted frames is expensive; do860// all stackwalking work in another thread for better GUI861// responsiveness862workerThread.invokeLater(new StackWalker(vframe, annoMemPanel) {863public void run() {864Address startAddr = null;865866// As this is a debugger, we want to provide potential crash867// information to the user, i.e., by marking signal handler frames868// on the stack. Since this system is currently targeted at869// annotating the Java frames (interpreted or compiled) on the870// stack and not, for example, "external" frames (note the current871// absence of a PC-to-symbol lookup mechanism at the Debugger872// level), we want to mark any Java frames which were interrupted873// by a signal. We do this by making two passes over the stack,874// one which finds signal handler frames and puts the parent875// frames in a table and one which finds Java frames and if they876// are in the table indicates that they were interrupted by a signal.877878Map<sun.jvm.hotspot.runtime.Frame, SignalInfo> interruptedFrameMap = new HashMap<>();879{880sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess();881RegisterMap tmpMap = thread.newRegisterMap(false);882while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {883if (tmpFrame.isSignalHandlerFrameDbg()) {884// Add some information to the map that we can extract later885sun.jvm.hotspot.runtime.Frame interruptedFrame = tmpFrame.sender(tmpMap);886SignalInfo info = new SignalInfo();887info.sigNum = tmpFrame.getSignalNumberDbg();888info.sigName = tmpFrame.getSignalNameDbg();889interruptedFrameMap.put(interruptedFrame, info);890}891tmpFrame = tmpFrame.sender(tmpMap);892}893}894895while (vf != null) {896String anno = null;897JavaVFrame curVFrame = vf;898sun.jvm.hotspot.runtime.Frame curFrame = curVFrame.getFrame();899Method interpreterFrameMethod = null;900901if (curVFrame.isInterpretedFrame()) {902anno = "Interpreted frame";903} else {904anno = "Compiled frame";905if (curVFrame.isDeoptimized()) {906anno += " (deoptimized)";907}908}909if (curVFrame.mayBeImpreciseDbg()) {910anno += "; information may be imprecise";911}912913if (curVFrame.isInterpretedFrame()) {914// Find the codelet915InterpreterCodelet codelet = VM.getVM().getInterpreter().getCodeletContaining(curFrame.getPC());916String description = null;917if (codelet != null) {918description = codelet.getDescription();919}920if (description == null) {921anno += "\n(Unknown interpreter codelet)";922} else {923anno += "\nExecuting in codelet \"" + description + "\" at PC = " + curFrame.getPC();924}925} else if (curVFrame.isCompiledFrame()) {926anno += "\nExecuting at PC = " + curFrame.getPC();927}928929if (startAddr == null) {930startAddr = curFrame.getSP();931}932933// FIXME: some compiled frames with empty oop map sets have been934// found (for example, Vector's inner Enumeration class, method935// "hasMoreElements"). Not sure yet why these cases are showing936// up -- should be possible (though unlikely) for safepoint code937// to patch the return instruction of these methods and then938// later attempt to get an oop map for that instruction. For939// now, we warn if we find such a method.940boolean shouldSkipOopMaps = false;941if (curVFrame.isCompiledFrame()) {942CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());943ImmutableOopMapSet maps = cb.getOopMaps();944if ((maps == null) || (maps.getCount() == 0)) {945shouldSkipOopMaps = true;946}947}948949// Add signal information to annotation if necessary950SignalInfo sigInfo = (SignalInfo) interruptedFrameMap.get(curFrame);951if (sigInfo != null) {952// This frame took a signal and we need to report it.953anno = (anno + "\n*** INTERRUPTED BY SIGNAL " + Integer.toString(sigInfo.sigNum) +954" (" + sigInfo.sigName + ")");955}956957JavaVFrame nextVFrame = curVFrame;958sun.jvm.hotspot.runtime.Frame nextFrame = curFrame;959do {960curVFrame = nextVFrame;961curFrame = nextFrame;962963try {964Method method = curVFrame.getMethod();965if (interpreterFrameMethod == null && curVFrame.isInterpretedFrame()) {966interpreterFrameMethod = method;967}968int bci = curVFrame.getBCI();969String lineNumberAnno = "";970if (method.hasLineNumberTable()) {971if ((bci == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ||972(bci >= 0 && bci < method.getCodeSize())) {973lineNumberAnno = ", line " + method.getLineNumberFromBCI(bci);974} else {975lineNumberAnno = " (INVALID BCI)";976}977}978anno += "\n" + method.getMethodHolder().getName().asString() + "." +979method.getName().asString() + method.getSignature().asString() +980"\n@bci " + bci + lineNumberAnno;981} catch (Exception e) {982anno += "\n(ERROR while iterating vframes for frame " + curFrame + ")";983}984985nextVFrame = curVFrame.javaSender();986if (nextVFrame != null) {987nextFrame = nextVFrame.getFrame();988}989} while (nextVFrame != null && nextFrame.equals(curFrame));990991if (shouldSkipOopMaps) {992anno = anno + "\nNOTE: null or empty ImmutableOopMapSet found for this CodeBlob";993}994995if (curFrame.getFP() != null) {996annoPanel.addAnnotation(new Annotation(curFrame.getSP(),997curFrame.getFP(),998anno));999} else {1000// For C2, which has null frame pointers on x86/amd64/aarch641001CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());1002Address sp = curFrame.getSP();1003if (Assert.ASSERTS_ENABLED) {1004Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");1005}1006annoPanel.addAnnotation(new Annotation(sp,1007sp.addOffsetTo(cb.getFrameSize()),1008anno));1009}10101011// Add interpreter frame annotations1012if (curFrame.isInterpretedFrame()) {1013annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameExpressionStack(),1014curFrame.addressOfInterpreterFrameTOS(),1015"Interpreter expression stack"));1016Address monBegin = curFrame.interpreterFrameMonitorBegin().address();1017Address monEnd = curFrame.interpreterFrameMonitorEnd().address();1018if (!monBegin.equals(monEnd)) {1019annoPanel.addAnnotation(new Annotation(monBegin, monEnd,1020"BasicObjectLocks"));1021}1022if (interpreterFrameMethod != null) {1023// The offset is just to get the right stack slots highlighted in the output1024int offset = 1;1025annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameLocal(offset),1026curFrame.addressOfInterpreterFrameLocal((int) interpreterFrameMethod.getMaxLocals() + offset),1027"Interpreter locals area for frame with SP = " + curFrame.getSP()));1028}1029String methodAnno = "Interpreter frame Method*";1030if (interpreterFrameMethod == null) {1031methodAnno += " (BAD OOP)";1032}1033Address a = curFrame.addressOfInterpreterFrameMethod();1034annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), methodAnno));1035a = curFrame.addressOfInterpreterFrameCPCache();1036annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), "Interpreter constant pool cache"));1037}10381039RegisterMap rm = (RegisterMap) vf.getRegisterMap().clone();1040if (!shouldSkipOopMaps) {1041try {1042curFrame.oopsDo(new AddressVisitor() {1043public void visitAddress(Address addr) {1044if (Assert.ASSERTS_ENABLED) {1045Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,1046"Address " + addr + "should have been aligned");1047}1048OopHandle handle = addr.getOopHandleAt(0);1049addAnnotation(addr, handle);1050}10511052public void visitCompOopAddress(Address addr) {1053if (Assert.ASSERTS_ENABLED) {1054Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,1055"Address " + addr + "should have been aligned");1056}1057OopHandle handle = addr.getCompOopHandleAt(0);1058addAnnotation(addr, handle);1059}10601061public void addAnnotation(Address addr, OopHandle handle) {1062// Check contents1063String anno = "null oop";1064if (handle != null) {1065// Find location1066CollectedHeap collHeap = VM.getVM().getUniverse().heap();1067boolean bad = true;1068anno = "BAD OOP";1069if (collHeap instanceof GenCollectedHeap) {1070GenCollectedHeap heap = (GenCollectedHeap) collHeap;1071for (int i = 0; i < heap.nGens(); i++) {1072if (heap.getGen(i).isIn(handle)) {1073if (i == 0) {1074anno = "NewGen ";1075} else if (i == 1) {1076anno = "OldGen ";1077} else {1078anno = "Gen " + i + " ";1079}1080bad = false;1081break;1082}1083}10841085} else if (collHeap instanceof G1CollectedHeap) {1086G1CollectedHeap heap = (G1CollectedHeap)collHeap;1087HeapRegion region = heap.hrm().getByAddress(handle);10881089if (region.isFree()) {1090anno = "Free ";1091bad = false;1092} else if (region.isYoung()) {1093anno = "Young ";1094bad = false;1095} else if (region.isHumongous()) {1096anno = "Humongous ";1097bad = false;1098} else if (region.isPinned()) {1099anno = "Pinned ";1100bad = false;1101} else if (region.isOld()) {1102anno = "Old ";1103bad = false;1104}1105} else if (collHeap instanceof ParallelScavengeHeap) {1106ParallelScavengeHeap heap = (ParallelScavengeHeap) collHeap;1107if (heap.youngGen().isIn(handle)) {1108anno = "PSYoungGen ";1109bad = false;1110} else if (heap.oldGen().isIn(handle)) {1111anno = "PSOldGen ";1112bad = false;1113}1114} else if (collHeap instanceof EpsilonHeap) {1115anno = "Epsilon ";1116bad = false;1117} else if (collHeap instanceof ShenandoahHeap) {1118ShenandoahHeap heap = (ShenandoahHeap) collHeap;1119anno = "ShenandoahHeap ";1120bad = false;1121} else if (collHeap instanceof ZCollectedHeap) {1122ZCollectedHeap heap = (ZCollectedHeap) collHeap;1123anno = "ZHeap ";1124bad = false;1125} else {1126// Optimistically assume the oop isn't bad1127anno = "[Unknown generation] ";1128bad = false;1129}11301131if (!bad) {1132try {1133Oop oop = VM.getVM().getObjectHeap().newOop(handle);1134if (oop instanceof Instance) {1135// Java-level objects always have workable names1136anno = anno + oop.getKlass().getName().asString();1137} else {1138ByteArrayOutputStream bos = new ByteArrayOutputStream();1139Oop.printOopValueOn(oop, new PrintStream(bos));1140anno = anno + bos.toString();1141}1142}1143catch (AddressException e) {1144anno += "CORRUPT OOP";1145}1146catch (NullPointerException e) {1147anno += "CORRUPT OOP (null pointer)";1148}1149}1150}11511152annoPanel.addAnnotation(new Annotation(addr, addr.addOffsetTo(addressSize), anno));1153}1154}, rm);1155} catch (Exception e) {1156System.err.println("Error while performing oopsDo for frame " + curFrame);1157e.printStackTrace();1158}1159}11601161vf = nextVFrame;1162}11631164// This used to paint as we walked the frames. This caused the display to be refreshed1165// enough to be annoying on remote displays. It also would cause the annotations to1166// be displayed in varying order which caused some annotations to overwrite others1167// depending on the races between painting and adding annotations. This latter problem1168// still exists to some degree but moving this code here definitely seems to reduce it1169annoPanel.makeVisible(startAddr);1170annoPanel.repaint();1171}1172});1173}11741175// Attach to existing JVMDebugger, which should be already attached to a core/process.1176private void attach(JVMDebugger d) {1177attached = true;1178showThreadsDialog();1179}11801181/** NOTE we are in a different thread here than either the main1182thread or the Swing/AWT event handler thread, so we must be very1183careful when creating or removing widgets */1184private void attach(int pid) {1185this.pid = pid;1186// Try to attach to this process1187Runnable remover = new Runnable() {1188public void run() {1189attachWaitDialog.setVisible(false);1190desktop.remove(attachWaitDialog);1191attachWaitDialog = null;1192}1193};11941195try {1196SwingUtilities.invokeLater(new Runnable() {1197public void run() {1198JOptionPane pane = new JOptionPane("Attaching to process " + pid + ", please wait...", JOptionPane.INFORMATION_MESSAGE);1199pane.setOptions(new Object[] {});1200attachWaitDialog = pane.createInternalFrame(desktop, "Attaching to Process");1201attachWaitDialog.show();1202}1203});12041205// FIXME: display exec'd debugger's output messages during this1206// lengthy call1207agent.attach(pid);1208if (agent.getDebugger().hasConsole()) {1209showDbgConsoleMenuItem.setEnabled(true);1210}1211attached = true;1212SwingUtilities.invokeLater(remover);1213}1214catch (DebuggerException e) {1215SwingUtilities.invokeLater(remover);1216final String errMsg = formatMessage(e.getMessage(), 80);1217SwingUtilities.invokeLater(new Runnable() {1218public void run() {1219setMenuItemsEnabled(attachMenuItems, true);1220JOptionPane.showInternalMessageDialog(desktop,1221"Unable to connect to process ID " + pid + ":\n\n" + errMsg,1222"Unable to Connect",1223JOptionPane.WARNING_MESSAGE);1224}1225});1226agent.detach();1227return;1228}12291230// OK, the VM should be available. Create the Threads dialog.1231showThreadsDialog();1232}12331234/** NOTE we are in a different thread here than either the main1235thread or the Swing/AWT event handler thread, so we must be very1236careful when creating or removing widgets */1237private void attach(final String executablePath, final String corePath) {1238// Try to open this core file1239Runnable remover = new Runnable() {1240public void run() {1241attachWaitDialog.setVisible(false);1242desktop.remove(attachWaitDialog);1243attachWaitDialog = null;1244}1245};12461247try {1248SwingUtilities.invokeLater(new Runnable() {1249public void run() {1250JOptionPane pane = new JOptionPane("Opening core file, please wait...", JOptionPane.INFORMATION_MESSAGE);1251pane.setOptions(new Object[] {});1252attachWaitDialog = pane.createInternalFrame(desktop, "Opening Core File");1253attachWaitDialog.show();1254}1255});12561257// FIXME: display exec'd debugger's output messages during this1258// lengthy call1259agent.attach(executablePath, corePath);1260if (agent.getDebugger().hasConsole()) {1261showDbgConsoleMenuItem.setEnabled(true);1262}1263attached = true;1264SwingUtilities.invokeLater(remover);1265}1266catch (DebuggerException e) {1267SwingUtilities.invokeLater(remover);1268final String errMsg = formatMessage(e.getMessage(), 80);1269SwingUtilities.invokeLater(new Runnable() {1270public void run() {1271setMenuItemsEnabled(attachMenuItems, true);1272JOptionPane.showInternalMessageDialog(desktop,1273"Unable to open core file\n" + corePath + ":\n\n" + errMsg,1274"Unable to Open Core File",1275JOptionPane.WARNING_MESSAGE);1276}1277});1278agent.detach();1279return;1280}12811282// OK, the VM should be available. Create the Threads dialog.1283showThreadsDialog();1284}12851286/** NOTE we are in a different thread here than either the main1287thread or the Swing/AWT event handler thread, so we must be very1288careful when creating or removing widgets */1289private void connect(final String debugServerName) {1290// Try to open this core file1291Runnable remover = new Runnable() {1292public void run() {1293attachWaitDialog.setVisible(false);1294desktop.remove(attachWaitDialog);1295attachWaitDialog = null;1296}1297};12981299try {1300SwingUtilities.invokeLater(new Runnable() {1301public void run() {1302JOptionPane pane = new JOptionPane("Connecting to debug server, please wait...", JOptionPane.INFORMATION_MESSAGE);1303pane.setOptions(new Object[] {});1304attachWaitDialog = pane.createInternalFrame(desktop, "Connecting to Debug Server");1305attachWaitDialog.show();1306}1307});13081309agent.attach(debugServerName);1310if (agent.getDebugger().hasConsole()) {1311showDbgConsoleMenuItem.setEnabled(true);1312}1313attached = true;1314SwingUtilities.invokeLater(remover);1315}1316catch (DebuggerException e) {1317SwingUtilities.invokeLater(remover);1318final String errMsg = formatMessage(e.getMessage(), 80);1319SwingUtilities.invokeLater(new Runnable() {1320public void run() {1321setMenuItemsEnabled(attachMenuItems, true);1322JOptionPane.showInternalMessageDialog(desktop,1323"Unable to connect to machine \"" + debugServerName + "\":\n\n" + errMsg,1324"Unable to Connect",1325JOptionPane.WARNING_MESSAGE);1326}1327});1328agent.detach();1329return;1330}13311332// OK, the VM should be available. Create the Threads dialog.1333showThreadsDialog();1334}13351336private void detachDebugger() {1337if (!attached) {1338return;1339}1340agent.detach();1341attached = false;1342}13431344private void detach() {1345detachDebugger();1346attachWaitDialog = null;1347threadsFrame = null;1348consoleFrame = null;1349setMenuItemsEnabled(attachMenuItems, true);1350setMenuItemsEnabled(detachMenuItems, false);1351toolsMenu.setEnabled(false);1352showDbgConsoleMenuItem.setEnabled(false);1353// FIXME: is this sufficient, or will I have to do anything else1354// to the components to kill them off? What about WorkerThreads?1355desktop.removeAll();1356desktop.invalidate();1357desktop.validate();1358desktop.repaint();1359}13601361/** NOTE that this is called from another thread than the main or1362Swing thread and we have to be careful about synchronization */1363private void showThreadsDialog() {1364SwingUtilities.invokeLater(new Runnable() {1365public void run() {1366threadsFrame = new JInternalFrame("Java Threads");1367threadsFrame.setResizable(true);1368threadsFrame.setIconifiable(true);1369JavaThreadsPanel threadsPanel = new JavaThreadsPanel();1370threadsPanel.addPanelListener(HSDB.this);1371threadsFrame.getContentPane().add(threadsPanel);1372threadsFrame.setSize(500, 300);1373threadsFrame.pack();1374desktop.add(threadsFrame);1375GraphicsUtilities.moveToInContainer(threadsFrame, 0.75f, 0.25f, 0, 20);1376threadsFrame.show();1377setMenuItemsEnabled(attachMenuItems, false);1378setMenuItemsEnabled(detachMenuItems, true);1379toolsMenu.setEnabled(true);1380VM.registerVMInitializedObserver(new Observer() {1381public void update(Observable o, Object data) {1382computeRevPtrsMenuItem.setEnabled(true);1383}1384});1385}1386});1387}13881389private void showObjectHistogram() {1390sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram();1391ObjectHistogramCleanupThunk cleanup =1392new ObjectHistogramCleanupThunk(histo);1393doHeapIteration("Object Histogram",1394"Generating histogram...",1395histo,1396cleanup);1397}13981399class ObjectHistogramCleanupThunk implements CleanupThunk {1400sun.jvm.hotspot.oops.ObjectHistogram histo;14011402ObjectHistogramCleanupThunk(sun.jvm.hotspot.oops.ObjectHistogram histo) {1403this.histo = histo;1404}14051406public void heapIterationComplete() {1407SwingUtilities.invokeLater(new Runnable() {1408public void run() {1409JInternalFrame histoFrame = new JInternalFrame("Object Histogram");1410histoFrame.setResizable(true);1411histoFrame.setClosable(true);1412histoFrame.setIconifiable(true);1413histoFrame.getContentPane().setLayout(new BorderLayout());1414ObjectHistogramPanel panel = new ObjectHistogramPanel(histo);1415panel.addPanelListener(HSDB.this);1416histoFrame.getContentPane().add(panel);1417desktop.add(histoFrame);1418GraphicsUtilities.reshapeToAspectRatio(histoFrame, 4.0f / 3.0f, 0.6f,1419histoFrame.getParent().getSize());1420GraphicsUtilities.centerInContainer(histoFrame);1421histoFrame.show();1422}1423});1424}1425}14261427public void showObjectsOfType(Klass type) {1428FindObjectByType finder = new FindObjectByType(type);1429FindObjectByTypeCleanupThunk cleanup =1430new FindObjectByTypeCleanupThunk(finder);1431ByteArrayOutputStream bos = new ByteArrayOutputStream();1432type.printValueOn(new PrintStream(bos));1433String typeName = bos.toString();1434doHeapIteration("Show Objects Of Type",1435"Finding instances of \"" + typeName + "\"",1436finder,1437cleanup);1438}14391440class FindObjectByTypeCleanupThunk implements CleanupThunk {1441FindObjectByType finder;14421443FindObjectByTypeCleanupThunk(FindObjectByType finder) {1444this.finder = finder;1445}14461447public void heapIterationComplete() {1448SwingUtilities.invokeLater(new Runnable() {1449public void run() {1450JInternalFrame finderFrame = new JInternalFrame("Show Objects of Type");1451finderFrame.getContentPane().setLayout(new BorderLayout());1452finderFrame.setResizable(true);1453finderFrame.setClosable(true);1454finderFrame.setIconifiable(true);1455ObjectListPanel panel = new ObjectListPanel(finder.getResults(),1456new HeapProgress("Reverse Pointers Analysis"));1457panel.addPanelListener(HSDB.this);1458finderFrame.getContentPane().add(panel);1459desktop.add(finderFrame);1460GraphicsUtilities.reshapeToAspectRatio(finderFrame, 4.0f / 3.0f, 0.6f,1461finderFrame.getParent().getSize());1462GraphicsUtilities.centerInContainer(finderFrame);1463finderFrame.show();1464}1465});1466}1467}14681469private void showDebuggerConsole() {1470if (consoleFrame == null) {1471consoleFrame = new JInternalFrame("Debugger Console");1472consoleFrame.setResizable(true);1473consoleFrame.setClosable(true);1474consoleFrame.setIconifiable(true);1475consoleFrame.getContentPane().setLayout(new BorderLayout());1476consoleFrame.getContentPane().add(new DebuggerConsolePanel(agent.getDebugger()), BorderLayout.CENTER);1477GraphicsUtilities.reshapeToAspectRatio(consoleFrame, 5.0f, 0.9f, desktop.getSize());1478}1479if (consoleFrame.getParent() == null) {1480desktop.add(consoleFrame);1481}1482consoleFrame.setVisible(true);1483consoleFrame.show();1484consoleFrame.getContentPane().getComponent(0).requestFocus();1485}14861487private void showConsole() {1488CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() {1489public HotSpotAgent getAgent() {1490return agent;1491}1492public boolean isAttached() {1493return attached;1494}1495public void attach(int pid) {1496HSDB.this.attach(pid);1497}1498public void attach(String java, String core) {1499}1500public void attach(String debugServerName) {1501HSDB.this.connect(debugServerName);1502}1503public void detach() {1504detachDebugger();1505}1506public void reattach() {1507if (attached) {1508detachDebugger();1509}1510if (pid != -1) {1511attach(pid);1512} else if (debugServerName != null) {1513connect(debugServerName);1514} else {1515attach(execPath, coreFilename);1516}1517}1518};15191520showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null)));1521}15221523private void showFindPanel() {1524showPanel("Find Pointer", new FindPanel());1525}15261527private void showFindInHeapPanel() {1528showPanel("Find Address In Heap", new FindInHeapPanel());1529}15301531private void showFindInCodeCachePanel() {1532showPanel("Find Address In Code Cache", new FindInCodeCachePanel());1533}15341535private void showHeapParametersPanel() {1536showPanel("Heap Parameters", new HeapParametersPanel());1537}15381539public void showThreadInfo(final JavaThread thread) {1540showPanel("Info for " + thread.getThreadName(), new ThreadInfoPanel(thread));1541}15421543public void showJavaStackTrace(final JavaThread thread) {1544JavaStackTracePanel jstp = new JavaStackTracePanel();1545showPanel("Java stack trace for " + thread.getThreadName(), jstp);1546jstp.setJavaThread(thread);1547}15481549private void showDeadlockDetectionPanel() {1550showPanel("Deadlock Detection", new DeadlockDetectionPanel());1551}15521553private void showMonitorCacheDumpPanel() {1554showPanel("Monitor Cache Dump", new MonitorCacheDumpPanel());1555}15561557public void showClassBrowser() {1558final JInternalFrame progressFrame = new JInternalFrame("Class Browser");1559progressFrame.setResizable(true);1560progressFrame.setClosable(true);1561progressFrame.setIconifiable(true);1562progressFrame.getContentPane().setLayout(new BorderLayout());1563final ProgressBarPanel bar = new ProgressBarPanel("Generating class list ..");1564bar.setIndeterminate(true);1565progressFrame.getContentPane().add(bar, BorderLayout.CENTER);1566desktop.add(progressFrame);1567progressFrame.pack();1568GraphicsUtilities.centerInContainer(progressFrame);1569progressFrame.show();15701571workerThread.invokeLater(new Runnable() {1572public void run() {1573HTMLGenerator htmlGen = new HTMLGenerator();1574InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses();1575final String htmlText = htmlGen.genHTMLForKlassNames(klasses);1576SwingUtilities.invokeLater(new Runnable() {1577public void run() {1578JInternalFrame cbFrame = new JInternalFrame("Class Browser");1579cbFrame.getContentPane().setLayout(new BorderLayout());1580cbFrame.setResizable(true);1581cbFrame.setClosable(true);1582cbFrame.setIconifiable(true);1583ClassBrowserPanel cbPanel = new ClassBrowserPanel();1584cbFrame.getContentPane().add(cbPanel, BorderLayout.CENTER);1585desktop.remove(progressFrame);1586desktop.repaint();1587desktop.add(cbFrame);1588GraphicsUtilities.reshapeToAspectRatio(cbFrame, 1.25f, 0.85f,1589cbFrame.getParent().getSize());1590cbFrame.show();1591cbPanel.setClassesText(htmlText);1592}1593});1594}1595});1596}15971598public void showCodeViewer() {1599showPanel("Code Viewer", new CodeViewerPanel(), 1.25f, 0.85f);1600}16011602public void showCodeViewer(final Address address) {1603final CodeViewerPanel panel = new CodeViewerPanel();1604showPanel("Code Viewer", panel, 1.25f, 0.85f);1605SwingUtilities.invokeLater(new Runnable() {1606public void run() {1607panel.viewAddress(address);1608}1609});16101611}16121613public void showMemoryViewer() {1614showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8));1615}16161617public void showCommandLineFlags() {1618showPanel("Command Line Flags", new VMFlagsPanel());1619}16201621public void showVMVersion() {1622showPanel("VM Version Info", new VMVersionInfoPanel());1623}16241625public void showSystemProperties() {1626showPanel("System Properties", new SysPropsPanel());1627}16281629private void showPanel(String name, JPanel panel) {1630showPanel(name, panel, 5.0f / 3.0f, 0.4f);1631}16321633private void showPanel(String name, JPanel panel, float aspectRatio, float fillRatio) {1634JInternalFrame frame = new JInternalFrame(name);1635frame.getContentPane().setLayout(new BorderLayout());1636frame.setResizable(true);1637frame.setClosable(true);1638frame.setIconifiable(true);1639frame.setMaximizable(true);1640frame.getContentPane().add(panel, BorderLayout.CENTER);1641desktop.add(frame);1642GraphicsUtilities.reshapeToAspectRatio(frame, aspectRatio, fillRatio, frame.getParent().getSize());1643GraphicsUtilities.randomLocation(frame);1644frame.show();1645if (panel instanceof SAPanel) {1646((SAPanel)panel).addPanelListener(this);1647}1648}16491650//--------------------------------------------------------------------------------1651// Framework for heap iteration with progress bar1652//16531654interface CleanupThunk {1655public void heapIterationComplete();1656}16571658class HeapProgress implements HeapProgressThunk {1659private JInternalFrame frame;1660private ProgressBarPanel bar;1661private String windowTitle;1662private String progressBarTitle;1663private CleanupThunk cleanup;16641665HeapProgress(String windowTitle) {1666this(windowTitle, "Percentage of heap visited", null);1667}16681669HeapProgress(String windowTitle, String progressBarTitle) {1670this(windowTitle, progressBarTitle, null);1671}16721673HeapProgress(String windowTitle, String progressBarTitle, CleanupThunk cleanup) {1674this.windowTitle = windowTitle;1675this.progressBarTitle = progressBarTitle;1676this.cleanup = cleanup;1677}16781679public void heapIterationFractionUpdate(final double fractionOfHeapVisited) {1680if (frame == null) {1681SwingUtilities.invokeLater(new Runnable() {1682public void run() {1683frame = new JInternalFrame(windowTitle);1684frame.setResizable(true);1685frame.setIconifiable(true);1686frame.getContentPane().setLayout(new BorderLayout());1687bar = new ProgressBarPanel(progressBarTitle);1688frame.getContentPane().add(bar, BorderLayout.CENTER);1689desktop.add(frame);1690frame.pack();1691GraphicsUtilities.constrainToSize(frame, frame.getParent().getSize());1692GraphicsUtilities.centerInContainer(frame);1693frame.show();1694}1695});1696}16971698SwingUtilities.invokeLater(new Runnable() {1699public void run() {1700bar.setValue(fractionOfHeapVisited);1701}1702});1703}17041705public void heapIterationComplete() {1706SwingUtilities.invokeLater(new Runnable() {1707public void run() {1708desktop.remove(frame);1709desktop.repaint();1710if (VM.getVM().getRevPtrs() != null) {1711// Ended up computing reverse pointers as a side-effect1712computeRevPtrsMenuItem.setEnabled(false);1713}1714}1715});17161717if (cleanup != null) {1718cleanup.heapIterationComplete();1719}1720}1721}17221723class VisitHeap implements Runnable {1724HeapVisitor visitor;17251726VisitHeap(HeapVisitor visitor) {1727this.visitor = visitor;1728}17291730public void run() {1731VM.getVM().getObjectHeap().iterate(visitor);1732}1733}17341735private void doHeapIteration(String frameTitle,1736String progressBarText,1737HeapVisitor visitor,1738CleanupThunk cleanup) {1739sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram();1740HeapProgress progress = new HeapProgress(frameTitle,1741progressBarText,1742cleanup);1743HeapVisitor progVisitor = new ProgressiveHeapVisitor(visitor, progress);1744workerThread.invokeLater(new VisitHeap(progVisitor));1745}17461747//--------------------------------------------------------------------------------1748// Stack trace helper1749//17501751private static JavaVFrame getLastJavaVFrame(JavaThread cur) {1752RegisterMap regMap = cur.newRegisterMap(true);1753sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess();1754if (f == null) return null;1755boolean imprecise = true;1756if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) {1757System.err.println("Correcting for invalid interpreter frame");1758f = f.sender(regMap);1759imprecise = false;1760}1761VFrame vf = VFrame.newVFrame(f, regMap, cur, true, imprecise);1762if (vf == null) {1763System.err.println(" (Unable to create vframe for topmost frame guess)");1764return null;1765}1766if (vf.isJavaFrame()) {1767return (JavaVFrame) vf;1768}1769return (JavaVFrame) vf.javaSender();1770}17711772// Internal routine for debugging1773private static void dumpStack(JavaThread cur) {1774RegisterMap regMap = cur.newRegisterMap(true);1775sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess();1776PrintStream tty = System.err;1777while (f != null) {1778tty.print("Found ");1779if (f.isInterpretedFrame()) { tty.print("interpreted"); }1780else if (f.isCompiledFrame()) { tty.print("compiled"); }1781else if (f.isEntryFrame()) { tty.print("entry"); }1782else if (f.isNativeFrame()) { tty.print("native"); }1783else if (f.isRuntimeFrame()) { tty.print("runtime"); }1784else { tty.print("external"); }1785tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP());1786if (f.isSignalHandlerFrameDbg()) {1787tty.print(" (SIGNAL HANDLER)");1788}1789tty.println();17901791if (!f.isFirstFrame()) {1792f = f.sender(regMap);1793} else {1794f = null;1795}1796}1797}17981799//--------------------------------------------------------------------------------1800// Component utilities1801//18021803private static JMenuItem createMenuItem(String name, ActionListener l) {1804JMenuItem item = new JMenuItem(name);1805item.addActionListener(l);1806return item;1807}18081809/** Punctuates the given string with \n's where necessary to not1810exceed the given number of characters per line. Strips1811extraneous whitespace. */1812private String formatMessage(String message, int charsPerLine) {1813StringBuilder buf = new StringBuilder(message.length());1814StringTokenizer tokenizer = new StringTokenizer(message);1815int curLineLength = 0;1816while (tokenizer.hasMoreTokens()) {1817String tok = tokenizer.nextToken();1818if (curLineLength + tok.length() > charsPerLine) {1819buf.append('\n');1820curLineLength = 0;1821} else {1822if (curLineLength != 0) {1823buf.append(' ');1824++curLineLength;1825}1826}1827buf.append(tok);1828curLineLength += tok.length();1829}1830return buf.toString();1831}18321833private void setMenuItemsEnabled(java.util.List<JMenuItem> items, boolean enabled) {1834for (Iterator<JMenuItem> iter = items.iterator(); iter.hasNext(); ) {1835iter.next().setEnabled(enabled);1836}1837}1838}183918401841