alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (HSDB.java)

This example Java source code file (HSDB.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

actionlistener, address, awt, borderlayout, bytearrayoutputstream, event, find, gui, heapprogress, hotspot, jbutton, jinternalframe, jpanel, jtextfield, jtree, math, object, runnable, string, tree

The HSDB.java Java example source code

/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.math.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;

import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.gc_implementation.parallelScavenge.*;
import sun.jvm.hotspot.gc_interface.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.ui.*;
import sun.jvm.hotspot.ui.tree.*;
import sun.jvm.hotspot.ui.classbrowser.*;
import sun.jvm.hotspot.utilities.*;

/** The top-level HotSpot Debugger. FIXME: make this an embeddable
    component! (Among other things, figure out what to do with the
    menu bar...) */

public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
  public static void main(String[] args) {
    new HSDB(args).run();
  }

  //--------------------------------------------------------------------------------
  // Internals only below this point
  //
  private HotSpotAgent agent;
  private JVMDebugger jvmDebugger;
  private JDesktopPane desktop;
  private boolean      attached;
  private boolean      argError;
  private JFrame frame;
  /** List <JMenuItem> */
  private java.util.List attachMenuItems;
  /** List <JMenuItem> */
  private java.util.List detachMenuItems;
  private JMenu toolsMenu;
  private JMenuItem showDbgConsoleMenuItem;
  private JMenuItem computeRevPtrsMenuItem;
  private JInternalFrame attachWaitDialog;
  private JInternalFrame threadsFrame;
  private JInternalFrame consoleFrame;
  private WorkerThread workerThread;
  // These had to be made data members because they are referenced in inner classes.
  private String pidText;
  private int pid;
  private String execPath;
  private String coreFilename;

  private void doUsage() {
    System.out.println("Usage:  java HSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]");
    System.out.println("           pid:                     attach to the process whose id is 'pid'");
    System.out.println("           path-to-java-executable: Debug a core file produced by this program");
    System.out.println("           path-to-corefile:        Debug this corefile.  The default is 'core'");
    System.out.println("        If no arguments are specified, you can select what to do from the GUI.\n");
    HotSpotAgent.showUsage();
    argError = true;
  }

  public HSDB(JVMDebugger d) {
    jvmDebugger = d;
  }

  private HSDB(String[] args) {
    switch (args.length) {
    case (0):
      break;

    case (1):
      if (args[0].equals("help") || args[0].equals("-help")) {
        doUsage();
      }
      // If all numbers, it is a PID to attach to
      // Else, it is a pathname to a .../bin/java for a core file.
      try {
        int unused = Integer.parseInt(args[0]);
        // If we get here, we have a PID and not a core file name
        pidText = args[0];
      } catch (NumberFormatException e) {
        execPath = args[0];
        coreFilename = "core";
      }
      break;

    case (2):
      execPath = args[0];
      coreFilename = args[1];
      break;

    default:
      System.out.println("HSDB Error: Too many options specified");
      doUsage();
    }
  }

  // close this tool without calling System.exit
  protected void closeUI() {
      workerThread.shutdown();
      frame.dispose();
  }

  public void run() {
    // Don't start the UI if there were bad arguments.
    if (argError) {
        return;
    }

    agent = new HotSpotAgent();
    workerThread = new WorkerThread();
    attachMenuItems = new java.util.ArrayList();
    detachMenuItems = new java.util.ArrayList();

    frame = new JFrame("HSDB - HotSpot Debugger");
    frame.setSize(800, 600);
    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    JMenuBar menuBar = new JMenuBar();

    //
    // File menu
    //

    JMenu menu = new JMenu("File");
    menu.setMnemonic(KeyEvent.VK_F);
    JMenuItem item;
    item = createMenuItem("Attach to HotSpot process...",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showAttachDialog();
                              }
                            });
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));
    item.setMnemonic(KeyEvent.VK_A);
    menu.add(item);
    attachMenuItems.add(item);

    item = createMenuItem("Open HotSpot core file...",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showOpenCoreFileDialog();
                              }
                            });
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK));
    item.setMnemonic(KeyEvent.VK_O);
    menu.add(item);
    attachMenuItems.add(item);

    item = createMenuItem("Connect to debug server...",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showConnectDialog();
                              }
                            });
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.ALT_MASK));
    item.setMnemonic(KeyEvent.VK_S);
    menu.add(item);
    attachMenuItems.add(item);

    item = createMenuItem("Detach",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                detach();
                              }
                            });
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
    item.setMnemonic(KeyEvent.VK_S);
    menu.add(item);
    detachMenuItems.add(item);

    // Disable detach menu items at first
    setMenuItemsEnabled(detachMenuItems, false);

    menu.addSeparator();

    item = createMenuItem("Exit",
                            new ActionListener() {
                                public void actionPerformed(ActionEvent e) {
                                  closeUI();
                                }
                              });
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
    item.setMnemonic(KeyEvent.VK_X);
    menu.add(item);
    menuBar.add(menu);

    //
    // Tools menu
    //

    toolsMenu = new JMenu("Tools");
    toolsMenu.setMnemonic(KeyEvent.VK_T);

    item = createMenuItem("Class Browser",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showClassBrowser();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_B);

    toolsMenu.add(item);

    item = createMenuItem("Code Viewer",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showCodeViewer();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_C);

    toolsMenu.add(item);


    item = createMenuItem("Compute Reverse Ptrs",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                fireComputeReversePtrs();
                              }
                            });
    computeRevPtrsMenuItem = item;
    item.setMnemonic(KeyEvent.VK_M);
    toolsMenu.add(item);

    item = createMenuItem("Deadlock Detection",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showDeadlockDetectionPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_D);
    toolsMenu.add(item);

    item = createMenuItem("Find Object by Query",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showFindByQueryPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_Q);
    toolsMenu.add(item);


    item = createMenuItem("Find Pointer",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showFindPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_P);
    toolsMenu.add(item);

    item = createMenuItem("Find Value In Heap",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showFindInHeapPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_V);
    toolsMenu.add(item);

    item = createMenuItem("Find Value In Code Cache",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showFindInCodeCachePanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_A);
    toolsMenu.add(item);

    item = createMenuItem("Heap Parameters",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showHeapParametersPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_H);
    toolsMenu.add(item);

    item = createMenuItem("Inspector",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showInspector(null);
                              }
                            });
    item.setMnemonic(KeyEvent.VK_R);
    item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK));
    toolsMenu.add(item);

    item = createMenuItem("Memory Viewer",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showMemoryViewer();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_M);
    toolsMenu.add(item);

    item = createMenuItem("Monitor Cache Dump",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showMonitorCacheDumpPanel();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_D);
    toolsMenu.add(item);

    item = createMenuItem("Object Histogram",
                          new ActionListener() {
                              public void actionPerformed(ActionEvent e) {
                                showObjectHistogram();
                              }
                            });
    item.setMnemonic(KeyEvent.VK_O);
    toolsMenu.add(item);

    item = createMenuItem("Show System Properties",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showSystemProperties();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_S);
    toolsMenu.add(item);

    item = createMenuItem("Show VM Version",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showVMVersion();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_M);
    toolsMenu.add(item);

    item = createMenuItem("Show -XX flags",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                showCommandLineFlags();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_X);
    toolsMenu.add(item);

    toolsMenu.setEnabled(false);
    menuBar.add(toolsMenu);

    //
    // Windows menu
    //

    JMenu windowsMenu = new JMenu("Windows");
    windowsMenu.setMnemonic(KeyEvent.VK_W);
    item = createMenuItem("Console",
                          new ActionListener() {
                             public void actionPerformed(ActionEvent e) {
                                 showConsole();
                             }
                          });
    item.setMnemonic(KeyEvent.VK_C);
    windowsMenu.add(item);
    showDbgConsoleMenuItem = createMenuItem("Debugger Console",
                                         new ActionListener() {
                                             public void actionPerformed(ActionEvent e) {
                                               showDebuggerConsole();
                                             }
                                           });
    showDbgConsoleMenuItem.setMnemonic(KeyEvent.VK_D);
    windowsMenu.add(showDbgConsoleMenuItem);
    showDbgConsoleMenuItem.setEnabled(false);

    menuBar.add(windowsMenu);


    frame.setJMenuBar(menuBar);

    desktop = new JDesktopPane();
    frame.getContentPane().add(desktop);
    GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize());
    GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize());
    frame.setVisible(true);

    Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
        public void run() {
          detachDebugger();
        }
      });

    // If jvmDebugger is already set, we have been given a JVMDebugger.
    // Otherwise, if pidText != null we are supposed to attach to it.
    // Finally, if execPath != null, it is the path of a jdk/bin/java
    // and coreFilename is the pathname of a core file we are
    // supposed to attach to.

    if (jvmDebugger != null) {
      attach(jvmDebugger);
    } else if (pidText != null) {
      attach(pidText);
    } else if (execPath != null) {
      attach(execPath, coreFilename);
    }
  }

  // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog
  private void showAttachDialog() {
    // FIXME: create filtered text field which only accepts numbers
    setMenuItemsEnabled(attachMenuItems, false);
    final JInternalFrame attachDialog = new JInternalFrame("Attach to HotSpot process");
    attachDialog.getContentPane().setLayout(new BorderLayout());

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    attachDialog.setBackground(panel.getBackground());

    panel.add(new JLabel("Enter process ID:"));
    final JTextField pidTextField = new JTextField(10);
    ActionListener attacher = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          attachDialog.setVisible(false);
          desktop.remove(attachDialog);
          workerThread.invokeLater(new Runnable() {
              public void run() {
                attach(pidTextField.getText());
              }
            });
        }
      };

    pidTextField.addActionListener(attacher);
    panel.add(pidTextField);
    attachDialog.getContentPane().add(panel, BorderLayout.NORTH);

    Box vbox = Box.createVerticalBox();
    panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
    JTextArea ta = new JTextArea(
                                 "Enter the process ID of a currently-running HotSpot process. On " +
                                 "Solaris and most Unix operating systems, this can be determined by " +
                                 "typing \"ps -u <your username> | grep java\"; the process ID is the " +
                                 "first number which appears on the resulting line. On Windows, the " +
                                 "process ID is present in the Task Manager, which can be brought up " +
                                 "while logged on to the desktop by pressing Ctrl-Alt-Delete.");
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setEditable(false);
    ta.setBackground(panel.getBackground());
    panel.add(ta);
    vbox.add(panel);

    Box hbox = Box.createHorizontalBox();
    hbox.add(Box.createGlue());
    JButton button = new JButton("OK");
    button.addActionListener(attacher);
    hbox.add(button);
    hbox.add(Box.createHorizontalStrut(20));
    button = new JButton("Cancel");
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          attachDialog.setVisible(false);
          desktop.remove(attachDialog);
          setMenuItemsEnabled(attachMenuItems, true);
        }
      });
    hbox.add(button);
    hbox.add(Box.createGlue());
    panel = new JPanel();
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    panel.add(hbox);
    vbox.add(panel);

    attachDialog.getContentPane().add(vbox, BorderLayout.SOUTH);

    desktop.add(attachDialog);
    attachDialog.setSize(400, 300);
    GraphicsUtilities.centerInContainer(attachDialog);
    attachDialog.show();
    pidTextField.requestFocus();
  }

  // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog
  private void showOpenCoreFileDialog() {
    setMenuItemsEnabled(attachMenuItems, false);
    final JInternalFrame dialog = new JInternalFrame("Open Core File");
    dialog.getContentPane().setLayout(new BorderLayout());

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    dialog.setBackground(panel.getBackground());

    Box hbox = Box.createHorizontalBox();
    Box vbox = Box.createVerticalBox();
    vbox.add(new JLabel("Path to core file:"));
    vbox.add(new JLabel("Path to Java executable:"));
    hbox.add(vbox);

    vbox = Box.createVerticalBox();
    final JTextField corePathField = new JTextField(40);
    final JTextField execPathField = new JTextField(40);
    vbox.add(corePathField);
    vbox.add(execPathField);
    hbox.add(vbox);

    final JButton browseCorePath = new JButton("Browse ..");
    final JButton browseExecPath = new JButton("Browse ..");
    browseCorePath.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                           JFileChooser fileChooser = new JFileChooser(new File("."));
                                           int retVal = fileChooser.showOpenDialog(dialog);
                                           if (retVal == JFileChooser.APPROVE_OPTION) {
                                              corePathField.setText(fileChooser.getSelectedFile().getPath());
                                           }
                                        }
                                     });
    browseExecPath.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                           JFileChooser fileChooser = new JFileChooser(new File("."));
                                           int retVal = fileChooser.showOpenDialog(dialog);
                                           if (retVal == JFileChooser.APPROVE_OPTION) {
                                              execPathField.setText(fileChooser.getSelectedFile().getPath());
                                           }
                                        }
                                     });
    vbox = Box.createVerticalBox();
    vbox.add(browseCorePath);
    vbox.add(browseExecPath);
    hbox.add(vbox);

    panel.add(hbox);
    dialog.getContentPane().add(panel, BorderLayout.NORTH);

    ActionListener attacher = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          dialog.setVisible(false);
          desktop.remove(dialog);
          workerThread.invokeLater(new Runnable() {
              public void run() {
                attach(execPathField.getText(), corePathField.getText());
              }
            });
        }
      };
    corePathField.addActionListener(attacher);
    execPathField.addActionListener(attacher);

    vbox = Box.createVerticalBox();
    panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
    JTextArea ta = new JTextArea(
                                 "Enter the full path names to the core file from a HotSpot process " +
                                 "and the Java executable from which it came. The latter is typically " +
                                 "located in the JDK/JRE directory under the directory " +
                                 "jre/bin/<arch>/native_threads.");
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setEditable(false);
    ta.setBackground(panel.getBackground());
    panel.add(ta);
    vbox.add(panel);

    hbox = Box.createHorizontalBox();
    hbox.add(Box.createGlue());
    JButton button = new JButton("OK");
    button.addActionListener(attacher);
    hbox.add(button);
    hbox.add(Box.createHorizontalStrut(20));
    button = new JButton("Cancel");
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          dialog.setVisible(false);
          desktop.remove(dialog);
          setMenuItemsEnabled(attachMenuItems, true);
        }
      });
    hbox.add(button);
    hbox.add(Box.createGlue());
    panel = new JPanel();
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    panel.add(hbox);
    vbox.add(panel);

    dialog.getContentPane().add(vbox, BorderLayout.SOUTH);

    desktop.add(dialog);
    dialog.setSize(500, 300);
    GraphicsUtilities.centerInContainer(dialog);
    dialog.show();
    corePathField.requestFocus();
  }

  // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog
  private void showConnectDialog() {
    // FIXME: create filtered text field which only accepts numbers
    setMenuItemsEnabled(attachMenuItems, false);
    final JInternalFrame dialog = new JInternalFrame("Connect to HotSpot Debug Server");
    dialog.getContentPane().setLayout(new BorderLayout());

    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    dialog.setBackground(panel.getBackground());

    panel.add(new JLabel("Enter machine name:"));
    final JTextField pidTextField = new JTextField(40);
    ActionListener attacher = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          dialog.setVisible(false);
          desktop.remove(dialog);
          workerThread.invokeLater(new Runnable() {
              public void run() {
                connect(pidTextField.getText());
              }
            });
        }
      };

    pidTextField.addActionListener(attacher);
    panel.add(pidTextField);
    dialog.getContentPane().add(panel, BorderLayout.NORTH);

    Box vbox = Box.createVerticalBox();
    panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    panel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
    JTextArea ta = new JTextArea(
                                 "Enter the name of a machine on which the HotSpot \"Debug Server\" is " +
                                 "running and is attached to a process or core file.");
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setEditable(false);
    ta.setBackground(panel.getBackground());
    panel.add(ta);
    vbox.add(panel);

    Box hbox = Box.createHorizontalBox();
    hbox.add(Box.createGlue());
    JButton button = new JButton("OK");
    button.addActionListener(attacher);
    hbox.add(button);
    hbox.add(Box.createHorizontalStrut(20));
    button = new JButton("Cancel");
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          dialog.setVisible(false);
          desktop.remove(dialog);
          setMenuItemsEnabled(attachMenuItems, true);
        }
      });
    hbox.add(button);
    hbox.add(Box.createGlue());
    panel = new JPanel();
    panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    panel.add(hbox);
    vbox.add(panel);

    dialog.getContentPane().add(vbox, BorderLayout.SOUTH);

    desktop.add(dialog);
    dialog.setSize(400, 300);
    GraphicsUtilities.centerInContainer(dialog);
    dialog.show();
    pidTextField.requestFocus();
  }

  public void showThreadOopInspector(JavaThread thread) {
    showInspector(new OopTreeNodeAdapter(thread.getThreadObj(), null));
  }

  public void showInspector(SimpleTreeNode adapter) {
    showPanel("Inspector", new Inspector(adapter), 1.0f, 0.65f);
  }

  public void showLiveness(Oop oop, LivenessPathList liveness) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    PrintStream tty = new PrintStream(bos);
    int numPaths = liveness.size();
    for (int i = 0; i < numPaths; i++) {
      tty.println("Path " + (i + 1) + " of " + numPaths + ":");
      liveness.get(i).printOn(tty);
    }
    JTextArea ta = new JTextArea(bos.toString());
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    ta.setEditable(false);

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());

    JScrollPane scroller = new JScrollPane();
    scroller.getViewport().add(ta);

    panel.add(scroller, BorderLayout.CENTER);

    bos = new ByteArrayOutputStream();
    tty = new PrintStream(bos);
    tty.print("Liveness result for ");
    Oop.printOopValueOn(oop, tty);

    JInternalFrame frame = new JInternalFrame(bos.toString());
    frame.setResizable(true);
    frame.setClosable(true);
    frame.setIconifiable(true);
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(panel, BorderLayout.CENTER);
    frame.pack();
    desktop.add(frame);
    GraphicsUtilities.reshapeToAspectRatio(frame, 0.5f / 0.2f, 0.5f, frame.getParent().getSize());
    frame.show();
  }

  private void fireComputeReversePtrs() {
    // Possible this might have been computed elsewhere
    if (VM.getVM().getRevPtrs() != null) {
      computeRevPtrsMenuItem.setEnabled(false);
      return;
    }

    workerThread.invokeLater(new Runnable() {
        public void run() {
          HeapProgress progress = new HeapProgress("Reverse Pointers Analysis");
          try {
            ReversePtrsAnalysis analysis = new ReversePtrsAnalysis();
            analysis.setHeapProgressThunk(progress);
            analysis.run();
            computeRevPtrsMenuItem.setEnabled(false);
          } catch (OutOfMemoryError e) {
            final String errMsg = formatMessage(e.toString(), 80);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                  JOptionPane.showInternalMessageDialog(desktop,
                                                        "Error computing reverse pointers:" + errMsg,
                                                        "Error",
                                                        JOptionPane.WARNING_MESSAGE);
                }
              });
          } finally {
            // make sure the progress bar goes away
            progress.heapIterationComplete();
          }
        }
      });
  }

  // Simple struct containing signal information
  class SignalInfo {
    public int sigNum;
    public String sigName;
  }

  // Need to have mutable vframe as well as visible memory panel
  abstract class StackWalker implements Runnable {
    protected JavaVFrame vf;
    protected AnnotatedMemoryPanel annoPanel;

    StackWalker(JavaVFrame vf, AnnotatedMemoryPanel annoPanel) {
      this.vf = vf;
      this.annoPanel = annoPanel;
    }
  }

  public void showThreadStackMemory(final JavaThread thread) {
    // dumpStack(thread);
    JavaVFrame vframe = getLastJavaVFrame(thread);
    if (vframe == null) {
      JOptionPane.showInternalMessageDialog(desktop,
                                            "Thread \"" + thread.getThreadName() +
                                            "\" has no Java frames on its stack",
                                            "Show Stack Memory",
                                            JOptionPane.INFORMATION_MESSAGE);
      return;
    }

    JInternalFrame stackFrame = new JInternalFrame("Stack Memory for " + thread.getThreadName());
    stackFrame.getContentPane().setLayout(new BorderLayout());
    stackFrame.setResizable(true);
    stackFrame.setClosable(true);
    stackFrame.setIconifiable(true);
    final long addressSize = agent.getTypeDataBase().getAddressSize();
    boolean is64Bit = (addressSize == 8);
    // This is somewhat of a  hack to guess a thread's stack limits since the
    // JavaThread doesn't support this functionality. However it is nice in that
    // it locks us into the active region of the thread's stack and not its
    // theoretical limits.
    //
    sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess();
    Address sp = tmpFrame.getSP();
    Address starting = sp;
    Address maxSP = starting;
    Address minSP = starting;
    RegisterMap tmpMap = thread.newRegisterMap(false);
    while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {
        tmpFrame = tmpFrame.sender(tmpMap);
        if (tmpFrame != null) {
          sp = tmpFrame.getSP();
          if (sp != null) {
            maxSP = AddressOps.max(maxSP, sp);
            minSP = AddressOps.min(minSP, sp);
          }
        }

    }
    // It is useful to be able to see say +/- 8K on the current stack range
    AnnotatedMemoryPanel annoMemPanel = new AnnotatedMemoryPanel(agent.getDebugger(), is64Bit, starting,
                                                                 minSP.addOffsetTo(-8192),
                                                                 maxSP.addOffsetTo( 8192));

    stackFrame.getContentPane().add(annoMemPanel, BorderLayout.CENTER);
    desktop.add(stackFrame);
    GraphicsUtilities.reshapeToAspectRatio(stackFrame, 4.0f / 3.0f, 0.85f, stackFrame.getParent().getSize());
    stackFrame.show();

    // Stackmap computation for interpreted frames is expensive; do
    // all stackwalking work in another thread for better GUI
    // responsiveness
    workerThread.invokeLater(new StackWalker(vframe, annoMemPanel) {
        public void run() {
          Address startAddr = null;

          // As this is a debugger, we want to provide potential crash
          // information to the user, i.e., by marking signal handler frames
          // on the stack. Since this system is currently targeted at
          // annotating the Java frames (interpreted or compiled) on the
          // stack and not, for example, "external" frames (note the current
          // absence of a PC-to-symbol lookup mechanism at the Debugger
          // level), we want to mark any Java frames which were interrupted
          // by a signal. We do this by making two passes over the stack,
          // one which finds signal handler frames and puts the parent
          // frames in a table and one which finds Java frames and if they
          // are in the table indicates that they were interrupted by a signal.

          Map interruptedFrameMap = new HashMap();
          {
            sun.jvm.hotspot.runtime.Frame tmpFrame = thread.getCurrentFrameGuess();
            RegisterMap tmpMap = thread.newRegisterMap(false);
            while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {
              if (tmpFrame.isSignalHandlerFrameDbg()) {
                // Add some information to the map that we can extract later
                sun.jvm.hotspot.runtime.Frame interruptedFrame = tmpFrame.sender(tmpMap);
                SignalInfo info = new SignalInfo();
                info.sigNum  = tmpFrame.getSignalNumberDbg();
                info.sigName = tmpFrame.getSignalNameDbg();
                interruptedFrameMap.put(interruptedFrame, info);
              }
              tmpFrame = tmpFrame.sender(tmpMap);
            }
          }

          while (vf != null) {
            String anno = null;
            JavaVFrame curVFrame = vf;
            sun.jvm.hotspot.runtime.Frame curFrame = curVFrame.getFrame();
            Method interpreterFrameMethod = null;

            if (curVFrame.isInterpretedFrame()) {
              anno = "Interpreted frame";
            } else {
              anno = "Compiled frame";
              if (curVFrame.isDeoptimized()) {
                anno += " (deoptimized)";
              }
            }
            if (curVFrame.mayBeImpreciseDbg()) {
              anno += "; information may be imprecise";
            }

            if (curVFrame.isInterpretedFrame()) {
              // Find the codelet
              InterpreterCodelet codelet = VM.getVM().getInterpreter().getCodeletContaining(curFrame.getPC());
              String description = null;
              if (codelet != null) {
                description = codelet.getDescription();
              }
              if (description == null) {
                anno += "\n(Unknown interpreter codelet)";
              } else {
                anno += "\nExecuting in codelet \"" + description + "\" at PC = " + curFrame.getPC();
              }
            } else if (curVFrame.isCompiledFrame()) {
              anno += "\nExecuting at PC = " + curFrame.getPC();
            }

            if (startAddr == null) {
              startAddr = curFrame.getSP();
            }

            // FIXME: some compiled frames with empty oop map sets have been
            // found (for example, Vector's inner Enumeration class, method
            // "hasMoreElements"). Not sure yet why these cases are showing
            // up -- should be possible (though unlikely) for safepoint code
            // to patch the return instruction of these methods and then
            // later attempt to get an oop map for that instruction. For
            // now, we warn if we find such a method.
            boolean shouldSkipOopMaps = false;
            if (curVFrame.isCompiledFrame()) {
              CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
              OopMapSet maps = cb.getOopMaps();
              if ((maps == null) || (maps.getSize() == 0)) {
                shouldSkipOopMaps = true;
              }
            }

            // Add signal information to annotation if necessary
            SignalInfo sigInfo = (SignalInfo) interruptedFrameMap.get(curFrame);
            if (sigInfo != null) {
              // This frame took a signal and we need to report it.
              anno = (anno + "\n*** INTERRUPTED BY SIGNAL " + Integer.toString(sigInfo.sigNum) +
                      " (" + sigInfo.sigName + ")");
            }

            JavaVFrame nextVFrame = curVFrame;
            sun.jvm.hotspot.runtime.Frame nextFrame = curFrame;
            do {
              curVFrame = nextVFrame;
              curFrame = nextFrame;

              try {
                Method method = curVFrame.getMethod();
                if (interpreterFrameMethod == null && curVFrame.isInterpretedFrame()) {
                  interpreterFrameMethod = method;
                }
                int bci = curVFrame.getBCI();
                String lineNumberAnno = "";
                if (method.hasLineNumberTable()) {
                  if ((bci == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ||
                      (bci >= 0 && bci < method.getCodeSize())) {
                    lineNumberAnno = ", line " + method.getLineNumberFromBCI(bci);
                  } else {
                    lineNumberAnno = " (INVALID BCI)";
                  }
                }
                anno += "\n" + method.getMethodHolder().getName().asString() + "." +
                               method.getName().asString() + method.getSignature().asString() +
                               "\n@bci " + bci + lineNumberAnno;
              } catch (Exception e) {
                anno += "\n(ERROR while iterating vframes for frame " + curFrame + ")";
              }

              nextVFrame = curVFrame.javaSender();
              if (nextVFrame != null) {
                nextFrame = nextVFrame.getFrame();
              }
            } while (nextVFrame != null && nextFrame.equals(curFrame));

            if (shouldSkipOopMaps) {
              anno = anno + "\nNOTE: null or empty OopMapSet found for this CodeBlob";
            }

            if (curFrame.getFP() != null) {
              annoPanel.addAnnotation(new Annotation(curFrame.getSP(),
                                                     curFrame.getFP(),
                                                     anno));
            } else {
              if (VM.getVM().getCPU().equals("x86") || VM.getVM().getCPU().equals("amd64")) {
                // For C2, which has null frame pointers on x86/amd64
                CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
                Address sp = curFrame.getSP();
                if (Assert.ASSERTS_ENABLED) {
                  Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
                }
                annoPanel.addAnnotation(new Annotation(sp,
                                                       sp.addOffsetTo(cb.getFrameSize()),
                                                       anno));
              } else {
                Assert.that(VM.getVM().getCPU().equals("ia64"), "only ia64 should reach here");
              }
            }

            // Add interpreter frame annotations
            if (curFrame.isInterpretedFrame()) {
              annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameExpressionStack(),
                                                     curFrame.addressOfInterpreterFrameTOS(),
                                                     "Interpreter expression stack"));
              Address monBegin = curFrame.interpreterFrameMonitorBegin().address();
              Address monEnd = curFrame.interpreterFrameMonitorEnd().address();
              if (!monBegin.equals(monEnd)) {
                  annoPanel.addAnnotation(new Annotation(monBegin, monEnd,
                                                         "BasicObjectLocks"));
              }
              if (interpreterFrameMethod != null) {
                // The offset is just to get the right stack slots highlighted in the output
                int offset = 1;
                annoPanel.addAnnotation(new Annotation(curFrame.addressOfInterpreterFrameLocal(offset),
                                                       curFrame.addressOfInterpreterFrameLocal((int) interpreterFrameMethod.getMaxLocals() + offset),
                                                       "Interpreter locals area for frame with SP = " + curFrame.getSP()));
              }
              String methodAnno = "Interpreter frame Method*";
              if (interpreterFrameMethod == null) {
                methodAnno += " (BAD OOP)";
              }
              Address a = curFrame.addressOfInterpreterFrameMethod();
              annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), methodAnno));
              a = curFrame.addressOfInterpreterFrameCPCache();
              annoPanel.addAnnotation(new Annotation(a, a.addOffsetTo(addressSize), "Interpreter constant pool cache"));
            }

            RegisterMap rm = (RegisterMap) vf.getRegisterMap().clone();
            if (!shouldSkipOopMaps) {
              try {
                curFrame.oopsDo(new AddressVisitor() {
                    public void visitAddress(Address addr) {
                      if (Assert.ASSERTS_ENABLED) {
                        Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,
                                    "Address " + addr + "should have been aligned");
                      }
                      OopHandle handle = addr.getOopHandleAt(0);
                      addAnnotation(addr, handle);
                    }

                    public void visitCompOopAddress(Address addr) {
                      if (Assert.ASSERTS_ENABLED) {
                        Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,
                                    "Address " + addr + "should have been aligned");
                      }
                      OopHandle handle = addr.getCompOopHandleAt(0);
                      addAnnotation(addr, handle);
                    }

                    public void addAnnotation(Address addr, OopHandle handle) {
                      // Check contents
                      String anno = "null oop";
                      if (handle != null) {
                        // Find location
                        CollectedHeap collHeap = VM.getVM().getUniverse().heap();
                        boolean bad = true;
                        anno = "BAD OOP";
                        if (collHeap instanceof GenCollectedHeap) {
                          GenCollectedHeap heap = (GenCollectedHeap) collHeap;
                          for (int i = 0; i < heap.nGens(); i++) {
                            if (heap.getGen(i).isIn(handle)) {
                              if (i == 0) {
                                anno = "NewGen ";
                              } else if (i == 1) {
                                anno = "OldGen ";
                              } else {
                                anno = "Gen " + i + " ";
                              }
                              bad = false;
                              break;
                            }
                          }

                        } else if (collHeap instanceof ParallelScavengeHeap) {
                          ParallelScavengeHeap heap = (ParallelScavengeHeap) collHeap;
                          if (heap.youngGen().isIn(handle)) {
                            anno = "PSYoungGen ";
                            bad = false;
                          } else if (heap.oldGen().isIn(handle)) {
                            anno = "PSOldGen ";
                            bad = false;
                          }
                        } else {
                          // Optimistically assume the oop isn't bad
                          anno = "[Unknown generation] ";
                          bad = false;
                        }

                        if (!bad) {
                          try {
                            Oop oop = VM.getVM().getObjectHeap().newOop(handle);
                            if (oop instanceof Instance) {
                                // Java-level objects always have workable names
                              anno = anno + oop.getKlass().getName().asString();
                            } else {
                              ByteArrayOutputStream bos = new ByteArrayOutputStream();
                              Oop.printOopValueOn(oop, new PrintStream(bos));
                              anno = anno + bos.toString();
                            }
                          }
                          catch (AddressException e) {
                            anno += "CORRUPT OOP";
                          }
                          catch (NullPointerException e) {
                            anno += "CORRUPT OOP (null pointer)";
                          }
                        }
                      }

                      annoPanel.addAnnotation(new Annotation(addr, addr.addOffsetTo(addressSize), anno));
                    }
                  }, rm);
              } catch (Exception e) {
                System.err.println("Error while performing oopsDo for frame " + curFrame);
                e.printStackTrace();
              }
            }

            vf = nextVFrame;
          }

          // This used to paint as we walked the frames. This caused the display to be refreshed
          // enough to be annoying on remote displays. It also would cause the annotations to
          // be displayed in varying order which caused some annotations to overwrite others
          // depending on the races between painting and adding annotations. This latter problem
          // still exists to some degree but moving this code here definitely seems to reduce it
          annoPanel.makeVisible(startAddr);
          annoPanel.repaint();
        }
      });
  }

  // Attach to existing JVMDebugger, which should be already attached to a core/process.
  private void attach(JVMDebugger d) {
    attached = true;
    showThreadsDialog();
  }

  /** NOTE we are in a different thread here than either the main
      thread or the Swing/AWT event handler thread, so we must be very
      careful when creating or removing widgets */
  private void attach(String pidText) {
      try {
      this.pidText = pidText;
      pid = Integer.parseInt(pidText);
    }
    catch (NumberFormatException e) {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setMenuItemsEnabled(attachMenuItems, true);
            JOptionPane.showInternalMessageDialog(desktop,
                                                  "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.",
                                                  "Parse error",
                                                  JOptionPane.WARNING_MESSAGE);
          }
        });
      return;
    }

    // Try to attach to this process
    Runnable remover = new Runnable() {
          public void run() {
            attachWaitDialog.setVisible(false);
            desktop.remove(attachWaitDialog);
            attachWaitDialog = null;
          }
      };

    try {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JOptionPane pane = new JOptionPane("Attaching to process " + pid + ", please wait...", JOptionPane.INFORMATION_MESSAGE);
            pane.setOptions(new Object[] {});
            attachWaitDialog = pane.createInternalFrame(desktop, "Attaching to Process");
            attachWaitDialog.show();
          }
        });

      // FIXME: display exec'd debugger's output messages during this
      // lengthy call
      agent.attach(pid);
      if (agent.getDebugger().hasConsole()) {
        showDbgConsoleMenuItem.setEnabled(true);
      }
      attached = true;
      SwingUtilities.invokeLater(remover);
    }
    catch (DebuggerException e) {
      SwingUtilities.invokeLater(remover);
      final String errMsg = formatMessage(e.getMessage(), 80);
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setMenuItemsEnabled(attachMenuItems, true);
            JOptionPane.showInternalMessageDialog(desktop,
                                                  "Unable to connect to process ID " + pid + ":\n\n" + errMsg,
                                                  "Unable to Connect",
                                                  JOptionPane.WARNING_MESSAGE);
          }
        });
      agent.detach();
      return;
    }

    // OK, the VM should be available. Create the Threads dialog.
    showThreadsDialog();
  }

  /** NOTE we are in a different thread here than either the main
      thread or the Swing/AWT event handler thread, so we must be very
      careful when creating or removing widgets */
  private void attach(final String executablePath, final String corePath) {
    // Try to open this core file
    Runnable remover = new Runnable() {
          public void run() {
            attachWaitDialog.setVisible(false);
            desktop.remove(attachWaitDialog);
            attachWaitDialog = null;
          }
      };

    try {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JOptionPane pane = new JOptionPane("Opening core file, please wait...", JOptionPane.INFORMATION_MESSAGE);
            pane.setOptions(new Object[] {});
            attachWaitDialog = pane.createInternalFrame(desktop, "Opening Core File");
            attachWaitDialog.show();
          }
        });

      // FIXME: display exec'd debugger's output messages during this
      // lengthy call
      agent.attach(executablePath, corePath);
      if (agent.getDebugger().hasConsole()) {
        showDbgConsoleMenuItem.setEnabled(true);
      }
      attached = true;
      SwingUtilities.invokeLater(remover);
    }
    catch (DebuggerException e) {
      SwingUtilities.invokeLater(remover);
      final String errMsg = formatMessage(e.getMessage(), 80);
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setMenuItemsEnabled(attachMenuItems, true);
            JOptionPane.showInternalMessageDialog(desktop,
                                                  "Unable to open core file\n" + corePath + ":\n\n" + errMsg,
                                                  "Unable to Open Core File",
                                                  JOptionPane.WARNING_MESSAGE);
          }
        });
      agent.detach();
      return;
    }

    // OK, the VM should be available. Create the Threads dialog.
    showThreadsDialog();
  }

  /** NOTE we are in a different thread here than either the main
      thread or the Swing/AWT event handler thread, so we must be very
      careful when creating or removing widgets */
  private void connect(final String remoteMachineName) {
    // Try to open this core file
    Runnable remover = new Runnable() {
          public void run() {
            attachWaitDialog.setVisible(false);
            desktop.remove(attachWaitDialog);
            attachWaitDialog = null;
          }
      };

    try {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JOptionPane pane = new JOptionPane("Connecting to debug server, please wait...", JOptionPane.INFORMATION_MESSAGE);
            pane.setOptions(new Object[] {});
            attachWaitDialog = pane.createInternalFrame(desktop, "Connecting to Debug Server");
            attachWaitDialog.show();
          }
        });

      agent.attach(remoteMachineName);
      if (agent.getDebugger().hasConsole()) {
        showDbgConsoleMenuItem.setEnabled(true);
      }
      attached = true;
      SwingUtilities.invokeLater(remover);
    }
    catch (DebuggerException e) {
      SwingUtilities.invokeLater(remover);
      final String errMsg = formatMessage(e.getMessage(), 80);
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            setMenuItemsEnabled(attachMenuItems, true);
            JOptionPane.showInternalMessageDialog(desktop,
                                                  "Unable to connect to machine \"" + remoteMachineName + "\":\n\n" + errMsg,
                                                  "Unable to Connect",
                                                  JOptionPane.WARNING_MESSAGE);
          }
        });
      agent.detach();
      return;
    }

    // OK, the VM should be available. Create the Threads dialog.
    showThreadsDialog();
  }

  private void detachDebugger() {
    if (!attached) {
      return;
    }
    agent.detach();
    attached = false;
  }

  private void detach() {
    detachDebugger();
    attachWaitDialog = null;
    threadsFrame = null;
    consoleFrame = null;
    setMenuItemsEnabled(attachMenuItems, true);
    setMenuItemsEnabled(detachMenuItems, false);
    toolsMenu.setEnabled(false);
    showDbgConsoleMenuItem.setEnabled(false);
    // FIXME: is this sufficient, or will I have to do anything else
    // to the components to kill them off? What about WorkerThreads?
    desktop.removeAll();
    desktop.invalidate();
    desktop.validate();
    desktop.repaint();
  }

  /** NOTE that this is called from another thread than the main or
      Swing thread and we have to be careful about synchronization */
  private void showThreadsDialog() {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          threadsFrame = new JInternalFrame("Java Threads");
          threadsFrame.setResizable(true);
          threadsFrame.setIconifiable(true);
          JavaThreadsPanel threadsPanel = new JavaThreadsPanel();
          threadsPanel.addPanelListener(HSDB.this);
          threadsFrame.getContentPane().add(threadsPanel);
          threadsFrame.setSize(500, 300);
          threadsFrame.pack();
          desktop.add(threadsFrame);
          GraphicsUtilities.moveToInContainer(threadsFrame, 0.75f, 0.25f, 0, 20);
          threadsFrame.show();
          setMenuItemsEnabled(attachMenuItems, false);
          setMenuItemsEnabled(detachMenuItems, true);
          toolsMenu.setEnabled(true);
          VM.registerVMInitializedObserver(new Observer() {
              public void update(Observable o, Object data) {
                computeRevPtrsMenuItem.setEnabled(true);
              }
            });
        }
      });
  }

  private void showObjectHistogram() {
    sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram();
    ObjectHistogramCleanupThunk cleanup =
      new ObjectHistogramCleanupThunk(histo);
    doHeapIteration("Object Histogram",
                    "Generating histogram...",
                    histo,
                    cleanup);
  }

  class ObjectHistogramCleanupThunk implements CleanupThunk {
    sun.jvm.hotspot.oops.ObjectHistogram histo;

    ObjectHistogramCleanupThunk(sun.jvm.hotspot.oops.ObjectHistogram histo) {
      this.histo = histo;
    }

    public void heapIterationComplete() {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JInternalFrame histoFrame = new JInternalFrame("Object Histogram");
            histoFrame.setResizable(true);
            histoFrame.setClosable(true);
            histoFrame.setIconifiable(true);
            histoFrame.getContentPane().setLayout(new BorderLayout());
            ObjectHistogramPanel panel = new ObjectHistogramPanel(histo);
            panel.addPanelListener(HSDB.this);
            histoFrame.getContentPane().add(panel);
            desktop.add(histoFrame);
            GraphicsUtilities.reshapeToAspectRatio(histoFrame, 4.0f / 3.0f, 0.6f,
                                       histoFrame.getParent().getSize());
            GraphicsUtilities.centerInContainer(histoFrame);
            histoFrame.show();
          }
        });
    }
  }

  public void showObjectsOfType(Klass type) {
    FindObjectByType finder = new FindObjectByType(type);
    FindObjectByTypeCleanupThunk cleanup =
      new FindObjectByTypeCleanupThunk(finder);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    type.printValueOn(new PrintStream(bos));
    String typeName = bos.toString();
    doHeapIteration("Show Objects Of Type",
                    "Finding instances of \"" + typeName + "\"",
                    finder,
                    cleanup);
  }

  class FindObjectByTypeCleanupThunk implements CleanupThunk {
    FindObjectByType finder;

    FindObjectByTypeCleanupThunk(FindObjectByType finder) {
      this.finder = finder;
    }

    public void heapIterationComplete() {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            JInternalFrame finderFrame = new JInternalFrame("Show Objects of Type");
            finderFrame.getContentPane().setLayout(new BorderLayout());
            finderFrame.setResizable(true);
            finderFrame.setClosable(true);
            finderFrame.setIconifiable(true);
            ObjectListPanel panel = new ObjectListPanel(finder.getResults(),
                                                        new HeapProgress("Reverse Pointers Analysis"));
            panel.addPanelListener(HSDB.this);
            finderFrame.getContentPane().add(panel);
            desktop.add(finderFrame);
            GraphicsUtilities.reshapeToAspectRatio(finderFrame, 4.0f / 3.0f, 0.6f,
                                       finderFrame.getParent().getSize());
            GraphicsUtilities.centerInContainer(finderFrame);
            finderFrame.show();
          }
        });
    }
  }

  private void showDebuggerConsole() {
    if (consoleFrame == null) {
      consoleFrame = new JInternalFrame("Debugger Console");
      consoleFrame.setResizable(true);
      consoleFrame.setClosable(true);
      consoleFrame.setIconifiable(true);
      consoleFrame.getContentPane().setLayout(new BorderLayout());
      consoleFrame.getContentPane().add(new DebuggerConsolePanel(agent.getDebugger()), BorderLayout.CENTER);
      GraphicsUtilities.reshapeToAspectRatio(consoleFrame, 5.0f, 0.9f, desktop.getSize());
    }
    if (consoleFrame.getParent() == null) {
      desktop.add(consoleFrame);
    }
    consoleFrame.setVisible(true);
    consoleFrame.show();
    consoleFrame.getContentPane().getComponent(0).requestFocus();
  }

  private void showConsole() {
      CommandProcessor.DebuggerInterface di = new CommandProcessor.DebuggerInterface() {
              public HotSpotAgent getAgent() {
                  return agent;
              }
              public boolean isAttached() {
                  return attached;
              }
              public void attach(String pid) {
                  attach(pid);
              }
              public void attach(String java, String core) {
              }
              public void detach() {
                  detachDebugger();
              }
              public void reattach() {
                  if (attached) {
                      detachDebugger();
                  }
                  if (pidText != null) {
                      attach(pidText);
                  } else {
                      attach(execPath, coreFilename);
                  }
              }
          };

      showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null)));
  }

  private void showFindByQueryPanel() {
    showPanel("Find Object by Query", new FindByQueryPanel());
  }

  private void showFindPanel() {
    showPanel("Find Pointer", new FindPanel());
  }

  private void showFindInHeapPanel() {
    showPanel("Find Address In Heap", new FindInHeapPanel());
  }

  private void showFindInCodeCachePanel() {
    showPanel("Find Address In Code Cache", new FindInCodeCachePanel());
  }

  private void showHeapParametersPanel() {
    showPanel("Heap Parameters", new HeapParametersPanel());
  }

  public void showThreadInfo(final JavaThread thread) {
    showPanel("Info for " + thread.getThreadName(), new ThreadInfoPanel(thread));
  }

  public void showJavaStackTrace(final JavaThread thread) {
    JavaStackTracePanel jstp = new JavaStackTracePanel();
    showPanel("Java stack trace for " + thread.getThreadName(), jstp);
    jstp.setJavaThread(thread);
  }

  private void showDeadlockDetectionPanel() {
    showPanel("Deadlock Detection", new DeadlockDetectionPanel());
  }

  private void showMonitorCacheDumpPanel() {
    showPanel("Monitor Cache Dump", new MonitorCacheDumpPanel());
  }

  public void showClassBrowser() {
    final JInternalFrame progressFrame = new JInternalFrame("Class Browser");
    progressFrame.setResizable(true);
    progressFrame.setClosable(true);
    progressFrame.setIconifiable(true);
    progressFrame.getContentPane().setLayout(new BorderLayout());
    final ProgressBarPanel bar = new ProgressBarPanel("Generating class list ..");
    bar.setIndeterminate(true);
    progressFrame.getContentPane().add(bar, BorderLayout.CENTER);
    desktop.add(progressFrame);
    progressFrame.pack();
    GraphicsUtilities.centerInContainer(progressFrame);
    progressFrame.show();

    workerThread.invokeLater(new Runnable() {
                                public void run() {
                                   HTMLGenerator htmlGen = new HTMLGenerator();
                                   InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses();
                                   final String htmlText = htmlGen.genHTMLForKlassNames(klasses);
                                   SwingUtilities.invokeLater(new Runnable() {
                                      public void run() {
                                         JInternalFrame cbFrame = new JInternalFrame("Class Browser");
                                         cbFrame.getContentPane().setLayout(new BorderLayout());
                                         cbFrame.setResizable(true);
                                         cbFrame.setClosable(true);
                                         cbFrame.setIconifiable(true);
                                         ClassBrowserPanel cbPanel = new ClassBrowserPanel();
                                         cbFrame.getContentPane().add(cbPanel, BorderLayout.CENTER);
                                         desktop.remove(progressFrame);
                                         desktop.repaint();
                                         desktop.add(cbFrame);
                                         GraphicsUtilities.reshapeToAspectRatio(cbFrame, 1.25f, 0.85f,
                                                                      cbFrame.getParent().getSize());
                                         cbFrame.show();
                                         cbPanel.setClassesText(htmlText);
                                      }
                                   });
                                }
                             });
  }

  public void showCodeViewer() {
    showPanel("Code Viewer", new CodeViewerPanel(), 1.25f, 0.85f);
  }

  public void showCodeViewer(final Address address) {
    final CodeViewerPanel panel = new CodeViewerPanel();
    showPanel("Code Viewer", panel, 1.25f, 0.85f);
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          panel.viewAddress(address);
        }
      });

  }

  public void showMemoryViewer() {
    showPanel("Memory Viewer", new MemoryViewer(agent.getDebugger(), agent.getTypeDataBase().getAddressSize() == 8));
  }

  public void showCommandLineFlags() {
    showPanel("Command Line Flags", new VMFlagsPanel());
  }

  public void showVMVersion() {
    showPanel("VM Version Info", new VMVersionInfoPanel());
  }

  public void showSystemProperties() {
    showPanel("System Properties", new SysPropsPanel());
  }

  private void showPanel(String name, JPanel panel) {
    showPanel(name, panel, 5.0f / 3.0f, 0.4f);
  }

  private void showPanel(String name, JPanel panel, float aspectRatio, float fillRatio) {
    JInternalFrame frame = new JInternalFrame(name);
    frame.getContentPane().setLayout(new BorderLayout());
    frame.setResizable(true);
    frame.setClosable(true);
    frame.setIconifiable(true);
    frame.setMaximizable(true);
    frame.getContentPane().add(panel, BorderLayout.CENTER);
    desktop.add(frame);
    GraphicsUtilities.reshapeToAspectRatio(frame, aspectRatio, fillRatio, frame.getParent().getSize());
    GraphicsUtilities.randomLocation(frame);
    frame.show();
    if (panel instanceof SAPanel) {
      ((SAPanel)panel).addPanelListener(this);
    }
  }

  //--------------------------------------------------------------------------------
  // Framework for heap iteration with progress bar
  //

  interface CleanupThunk {
    public void heapIterationComplete();
  }

  class HeapProgress implements HeapProgressThunk {
    private JInternalFrame frame;
    private ProgressBarPanel bar;
    private String windowTitle;
    private String progressBarTitle;
    private CleanupThunk cleanup;

    HeapProgress(String windowTitle) {
      this(windowTitle, "Percentage of heap visited", null);
    }

    HeapProgress(String windowTitle, String progressBarTitle) {
      this(windowTitle, progressBarTitle, null);
    }

    HeapProgress(String windowTitle, String progressBarTitle, CleanupThunk cleanup) {
      this.windowTitle = windowTitle;
      this.progressBarTitle = progressBarTitle;
      this.cleanup = cleanup;
    }

    public void heapIterationFractionUpdate(final double fractionOfHeapVisited) {
      if (frame == null) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              frame = new JInternalFrame(windowTitle);
              frame.setResizable(true);
              frame.setIconifiable(true);
              frame.getContentPane().setLayout(new BorderLayout());
              bar = new ProgressBarPanel(progressBarTitle);
              frame.getContentPane().add(bar, BorderLayout.CENTER);
              desktop.add(frame);
              frame.pack();
              GraphicsUtilities.constrainToSize(frame, frame.getParent().getSize());
              GraphicsUtilities.centerInContainer(frame);
              frame.show();
            }
          });
      }

      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            bar.setValue(fractionOfHeapVisited);
          }
        });
    }

    public void heapIterationComplete() {
      SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            desktop.remove(frame);
            desktop.repaint();
            if (VM.getVM().getRevPtrs() != null) {
              // Ended up computing reverse pointers as a side-effect
              computeRevPtrsMenuItem.setEnabled(false);
            }
          }
        });

      if (cleanup != null) {
        cleanup.heapIterationComplete();
      }
    }
  }

  class VisitHeap implements Runnable {
    HeapVisitor visitor;

    VisitHeap(HeapVisitor visitor) {
      this.visitor = visitor;
    }

    public void run() {
      VM.getVM().getObjectHeap().iterate(visitor);
    }
  }

  private void doHeapIteration(String frameTitle,
                               String progressBarText,
                               HeapVisitor visitor,
                               CleanupThunk cleanup) {
    sun.jvm.hotspot.oops.ObjectHistogram histo = new sun.jvm.hotspot.oops.ObjectHistogram();
    HeapProgress progress = new HeapProgress(frameTitle,
                                             progressBarText,
                                             cleanup);
    HeapVisitor progVisitor = new ProgressiveHeapVisitor(visitor, progress);
    workerThread.invokeLater(new VisitHeap(progVisitor));
  }

  //--------------------------------------------------------------------------------
  // Stack trace helper
  //

  private static JavaVFrame getLastJavaVFrame(JavaThread cur) {
    RegisterMap regMap = cur.newRegisterMap(true);
    sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess();
    if (f == null) return null;
    boolean imprecise = true;
    if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) {
      System.err.println("Correcting for invalid interpreter frame");
      f = f.sender(regMap);
      imprecise = false;
    }
    VFrame vf = VFrame.newVFrame(f, regMap, cur, true, imprecise);
    if (vf == null) {
      System.err.println(" (Unable to create vframe for topmost frame guess)");
      return null;
    }
    if (vf.isJavaFrame()) {
      return (JavaVFrame) vf;
    }
    return (JavaVFrame) vf.javaSender();
  }

  // Internal routine for debugging
  private static void dumpStack(JavaThread cur) {
    RegisterMap regMap = cur.newRegisterMap(true);
    sun.jvm.hotspot.runtime.Frame f = cur.getCurrentFrameGuess();
    PrintStream tty = System.err;
    while (f != null) {
      tty.print("Found ");
           if (f.isInterpretedFrame()) { tty.print("interpreted"); }
      else if (f.isCompiledFrame())    { tty.print("compiled"); }
      else if (f.isEntryFrame())       { tty.print("entry"); }
      else if (f.isNativeFrame())      { tty.print("native"); }
      else if (f.isRuntimeFrame())     { tty.print("runtime"); }
      else { tty.print("external"); }
      tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP());
      if (f.isSignalHandlerFrameDbg()) {
        tty.print(" (SIGNAL HANDLER)");
      }
      tty.println();

      if (!f.isFirstFrame()) {
        f = f.sender(regMap);
      } else {
        f = null;
      }
    }
  }

  //--------------------------------------------------------------------------------
  // Component utilities
  //

  private static JMenuItem createMenuItem(String name, ActionListener l) {
    JMenuItem item = new JMenuItem(name);
    item.addActionListener(l);
    return item;
  }

  /** Punctuates the given string with \n's where necessary to not
      exceed the given number of characters per line. Strips
      extraneous whitespace. */
  private String formatMessage(String message, int charsPerLine) {
    StringBuffer buf = new StringBuffer(message.length());
    StringTokenizer tokenizer = new StringTokenizer(message);
    int curLineLength = 0;
    while (tokenizer.hasMoreTokens()) {
      String tok = tokenizer.nextToken();
      if (curLineLength + tok.length() > charsPerLine) {
        buf.append('\n');
        curLineLength = 0;
      } else {
        if (curLineLength != 0) {
          buf.append(' ');
          ++curLineLength;
        }
      }
      buf.append(tok);
      curLineLength += tok.length();
    }
    return buf.toString();
  }

  private void setMenuItemsEnabled(java.util.List items, boolean enabled) {
    for (Iterator iter = items.iterator(); iter.hasNext(); ) {
      ((JMenuItem) iter.next()).setEnabled(enabled);
    }
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java HSDB.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.