agent/src/share/classes/sun/jvm/hotspot/HSDB.java

Print this page




  42 import sun.jvm.hotspot.oops.*;
  43 import sun.jvm.hotspot.runtime.*;
  44 import sun.jvm.hotspot.ui.*;
  45 import sun.jvm.hotspot.ui.tree.*;
  46 import sun.jvm.hotspot.ui.classbrowser.*;
  47 import sun.jvm.hotspot.utilities.*;
  48 
  49 /** The top-level HotSpot Debugger. FIXME: make this an embeddable
  50     component! (Among other things, figure out what to do with the
  51     menu bar...) */
  52 
  53 public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
  54   public static void main(String[] args) {
  55     new HSDB(args).run();
  56   }
  57 
  58   //--------------------------------------------------------------------------------
  59   // Internals only below this point
  60   //
  61   private HotSpotAgent agent;

  62   private JDesktopPane desktop;
  63   private boolean      attached;


  64   /** List <JMenuItem> */
  65   private java.util.List attachMenuItems;
  66   /** List <JMenuItem> */
  67   private java.util.List detachMenuItems;
  68   private JMenu toolsMenu;
  69   private JMenuItem showDbgConsoleMenuItem;
  70   private JMenuItem computeRevPtrsMenuItem;
  71   private JInternalFrame attachWaitDialog;
  72   private JInternalFrame threadsFrame;
  73   private JInternalFrame consoleFrame;
  74   private WorkerThread workerThread;
  75   // These had to be made data members because they are referenced in inner classes.
  76   private String pidText;
  77   private int pid;
  78   private String execPath;
  79   private String coreFilename;
  80 
  81   private void doUsage() {
  82     System.out.println("Usage:  java HSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]");
  83     System.out.println("           pid:                     attach to the process whose id is 'pid'");
  84     System.out.println("           path-to-java-executable: Debug a core file produced by this program");
  85     System.out.println("           path-to-corefile:        Debug this corefile.  The default is 'core'");
  86     System.out.println("        If no arguments are specified, you can select what to do from the GUI.\n");
  87     HotSpotAgent.showUsage();





  88   }
  89 
  90   private HSDB(String[] args) {
  91     switch (args.length) {
  92     case (0):
  93       break;
  94 
  95     case (1):
  96       if (args[0].equals("help") || args[0].equals("-help")) {
  97         doUsage();
  98         System.exit(0);
  99       }
 100       // If all numbers, it is a PID to attach to
 101       // Else, it is a pathname to a .../bin/java for a core file.
 102       try {
 103         int unused = Integer.parseInt(args[0]);
 104         // If we get here, we have a PID and not a core file name
 105         pidText = args[0];
 106       } catch (NumberFormatException e) {
 107         execPath = args[0];
 108         coreFilename = "core";
 109       }
 110       break;
 111 
 112     case (2):
 113       execPath = args[0];
 114       coreFilename = args[1];
 115       break;
 116 
 117     default:
 118       System.out.println("HSDB Error: Too many options specified");
 119       doUsage();
 120       System.exit(1);
 121     }
 122   }
 123 
 124   private void run() {
 125     // At this point, if pidText != null we are supposed to attach to it.
 126     // Else, if execPath != null, it is the path of a jdk/bin/java
 127     // and coreFilename is the pathname of a core file we are
 128     // supposed to attach to.






 129 
 130     agent = new HotSpotAgent();
 131     workerThread = new WorkerThread();
 132     attachMenuItems = new java.util.ArrayList();
 133     detachMenuItems = new java.util.ArrayList();
 134 
 135     JFrame frame = new JFrame("HSDB - HotSpot Debugger");
 136     frame.setSize(800, 600);
 137     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 138 
 139     JMenuBar menuBar = new JMenuBar();
 140 
 141     //
 142     // File menu
 143     //
 144 
 145     JMenu menu = new JMenu("File");
 146     menu.setMnemonic(KeyEvent.VK_F);
 147     JMenuItem item;
 148     item = createMenuItem("Attach to HotSpot process...",
 149                           new ActionListener() {
 150                               public void actionPerformed(ActionEvent e) {
 151                                 showAttachDialog();
 152                               }
 153                             });
 154     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));
 155     item.setMnemonic(KeyEvent.VK_A);
 156     menu.add(item);
 157     attachMenuItems.add(item);


 180 
 181     item = createMenuItem("Detach",
 182                           new ActionListener() {
 183                               public void actionPerformed(ActionEvent e) {
 184                                 detach();
 185                               }
 186                             });
 187     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
 188     item.setMnemonic(KeyEvent.VK_S);
 189     menu.add(item);
 190     detachMenuItems.add(item);
 191 
 192     // Disable detach menu items at first
 193     setMenuItemsEnabled(detachMenuItems, false);
 194 
 195     menu.addSeparator();
 196 
 197     item = createMenuItem("Exit",
 198                             new ActionListener() {
 199                                 public void actionPerformed(ActionEvent e) {
 200                                   System.exit(0);
 201                                 }
 202                               });
 203     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
 204     item.setMnemonic(KeyEvent.VK_X);
 205     menu.add(item);
 206     menuBar.add(menu);
 207 
 208     //
 209     // Tools menu
 210     //
 211 
 212     toolsMenu = new JMenu("Tools");
 213     toolsMenu.setMnemonic(KeyEvent.VK_T);
 214 
 215     item = createMenuItem("Class Browser",
 216                           new ActionListener() {
 217                              public void actionPerformed(ActionEvent e) {
 218                                 showClassBrowser();
 219                              }
 220                           });


 389     windowsMenu.add(showDbgConsoleMenuItem);
 390     showDbgConsoleMenuItem.setEnabled(false);
 391 
 392     menuBar.add(windowsMenu);
 393 
 394 
 395     frame.setJMenuBar(menuBar);
 396 
 397     desktop = new JDesktopPane();
 398     frame.getContentPane().add(desktop);
 399     GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize());
 400     GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize());
 401     frame.setVisible(true);
 402 
 403     Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
 404         public void run() {
 405           detachDebugger();
 406         }
 407       });
 408 
 409     if (pidText != null) {








 410       attach(pidText);
 411     } else if (execPath != null) {
 412       attach(execPath, coreFilename);
 413     }
 414   }
 415 
 416   // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog
 417   private void showAttachDialog() {
 418     // FIXME: create filtered text field which only accepts numbers
 419     setMenuItemsEnabled(attachMenuItems, false);
 420     final JInternalFrame attachDialog = new JInternalFrame("Attach to HotSpot process");
 421     attachDialog.getContentPane().setLayout(new BorderLayout());
 422 
 423     JPanel panel = new JPanel();
 424     panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
 425     panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
 426     attachDialog.setBackground(panel.getBackground());
 427 
 428     panel.add(new JLabel("Enter process ID:"));
 429     final JTextField pidTextField = new JTextField(10);


1094                     }
1095                   }, rm);
1096               } catch (Exception e) {
1097                 System.err.println("Error while performing oopsDo for frame " + curFrame);
1098                 e.printStackTrace();
1099               }
1100             }
1101 
1102             vf = nextVFrame;
1103           }
1104 
1105           // This used to paint as we walked the frames. This caused the display to be refreshed
1106           // enough to be annoying on remote displays. It also would cause the annotations to
1107           // be displayed in varying order which caused some annotations to overwrite others
1108           // depending on the races between painting and adding annotations. This latter problem
1109           // still exists to some degree but moving this code here definitely seems to reduce it
1110           annoPanel.makeVisible(startAddr);
1111           annoPanel.repaint();
1112         }
1113       });






1114   }
1115 
1116   /** NOTE we are in a different thread here than either the main
1117       thread or the Swing/AWT event handler thread, so we must be very
1118       careful when creating or removing widgets */
1119   private void attach(String pidText) {
1120       try {
1121       this.pidText = pidText;
1122       pid = Integer.parseInt(pidText);
1123     }
1124     catch (NumberFormatException e) {
1125       SwingUtilities.invokeLater(new Runnable() {
1126           public void run() {
1127             setMenuItemsEnabled(attachMenuItems, true);
1128             JOptionPane.showInternalMessageDialog(desktop,
1129                                                   "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.",
1130                                                   "Parse error",
1131                                                   JOptionPane.WARNING_MESSAGE);
1132           }
1133         });




  42 import sun.jvm.hotspot.oops.*;
  43 import sun.jvm.hotspot.runtime.*;
  44 import sun.jvm.hotspot.ui.*;
  45 import sun.jvm.hotspot.ui.tree.*;
  46 import sun.jvm.hotspot.ui.classbrowser.*;
  47 import sun.jvm.hotspot.utilities.*;
  48 
  49 /** The top-level HotSpot Debugger. FIXME: make this an embeddable
  50     component! (Among other things, figure out what to do with the
  51     menu bar...) */
  52 
  53 public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
  54   public static void main(String[] args) {
  55     new HSDB(args).run();
  56   }
  57 
  58   //--------------------------------------------------------------------------------
  59   // Internals only below this point
  60   //
  61   private HotSpotAgent agent;
  62   private JVMDebugger jvmDebugger;
  63   private JDesktopPane desktop;
  64   private boolean      attached;
  65   private boolean      argError;
  66   private JFrame frame;
  67   /** List <JMenuItem> */
  68   private java.util.List attachMenuItems;
  69   /** List <JMenuItem> */
  70   private java.util.List detachMenuItems;
  71   private JMenu toolsMenu;
  72   private JMenuItem showDbgConsoleMenuItem;
  73   private JMenuItem computeRevPtrsMenuItem;
  74   private JInternalFrame attachWaitDialog;
  75   private JInternalFrame threadsFrame;
  76   private JInternalFrame consoleFrame;
  77   private WorkerThread workerThread;
  78   // These had to be made data members because they are referenced in inner classes.
  79   private String pidText;
  80   private int pid;
  81   private String execPath;
  82   private String coreFilename;
  83 
  84   private void doUsage() {
  85     System.out.println("Usage:  java HSDB [[pid] | [path-to-java-executable [path-to-corefile]] | help ]");
  86     System.out.println("           pid:                     attach to the process whose id is 'pid'");
  87     System.out.println("           path-to-java-executable: Debug a core file produced by this program");
  88     System.out.println("           path-to-corefile:        Debug this corefile.  The default is 'core'");
  89     System.out.println("        If no arguments are specified, you can select what to do from the GUI.\n");
  90     HotSpotAgent.showUsage();
  91     argError = true;
  92   }
  93 
  94   public HSDB(JVMDebugger d) {
  95     jvmDebugger = d;
  96   }
  97 
  98   private HSDB(String[] args) {
  99     switch (args.length) {
 100     case (0):
 101       break;
 102 
 103     case (1):
 104       if (args[0].equals("help") || args[0].equals("-help")) {
 105         doUsage();

 106       }
 107       // If all numbers, it is a PID to attach to
 108       // Else, it is a pathname to a .../bin/java for a core file.
 109       try {
 110         int unused = Integer.parseInt(args[0]);
 111         // If we get here, we have a PID and not a core file name
 112         pidText = args[0];
 113       } catch (NumberFormatException e) {
 114         execPath = args[0];
 115         coreFilename = "core";
 116       }
 117       break;
 118 
 119     case (2):
 120       execPath = args[0];
 121       coreFilename = args[1];
 122       break;
 123 
 124     default:
 125       System.out.println("HSDB Error: Too many options specified");
 126       doUsage();

 127     }
 128   }
 129 
 130   // close this tool without calling System.exit
 131   protected void closeUI() {
 132       workerThread.shutdown();
 133       frame.dispose();
 134   }
 135 
 136   public void run() {
 137     // Don't start the UI if there were bad arguments.
 138     if (argError) {
 139         return;
 140     }
 141 
 142     agent = new HotSpotAgent();
 143     workerThread = new WorkerThread();
 144     attachMenuItems = new java.util.ArrayList();
 145     detachMenuItems = new java.util.ArrayList();
 146 
 147     frame = new JFrame("HSDB - HotSpot Debugger");
 148     frame.setSize(800, 600);
 149     frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
 150 
 151     JMenuBar menuBar = new JMenuBar();
 152 
 153     //
 154     // File menu
 155     //
 156 
 157     JMenu menu = new JMenu("File");
 158     menu.setMnemonic(KeyEvent.VK_F);
 159     JMenuItem item;
 160     item = createMenuItem("Attach to HotSpot process...",
 161                           new ActionListener() {
 162                               public void actionPerformed(ActionEvent e) {
 163                                 showAttachDialog();
 164                               }
 165                             });
 166     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));
 167     item.setMnemonic(KeyEvent.VK_A);
 168     menu.add(item);
 169     attachMenuItems.add(item);


 192 
 193     item = createMenuItem("Detach",
 194                           new ActionListener() {
 195                               public void actionPerformed(ActionEvent e) {
 196                                 detach();
 197                               }
 198                             });
 199     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
 200     item.setMnemonic(KeyEvent.VK_S);
 201     menu.add(item);
 202     detachMenuItems.add(item);
 203 
 204     // Disable detach menu items at first
 205     setMenuItemsEnabled(detachMenuItems, false);
 206 
 207     menu.addSeparator();
 208 
 209     item = createMenuItem("Exit",
 210                             new ActionListener() {
 211                                 public void actionPerformed(ActionEvent e) {
 212                                   closeUI();
 213                                 }
 214                               });
 215     item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
 216     item.setMnemonic(KeyEvent.VK_X);
 217     menu.add(item);
 218     menuBar.add(menu);
 219 
 220     //
 221     // Tools menu
 222     //
 223 
 224     toolsMenu = new JMenu("Tools");
 225     toolsMenu.setMnemonic(KeyEvent.VK_T);
 226 
 227     item = createMenuItem("Class Browser",
 228                           new ActionListener() {
 229                              public void actionPerformed(ActionEvent e) {
 230                                 showClassBrowser();
 231                              }
 232                           });


 401     windowsMenu.add(showDbgConsoleMenuItem);
 402     showDbgConsoleMenuItem.setEnabled(false);
 403 
 404     menuBar.add(windowsMenu);
 405 
 406 
 407     frame.setJMenuBar(menuBar);
 408 
 409     desktop = new JDesktopPane();
 410     frame.getContentPane().add(desktop);
 411     GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize());
 412     GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize());
 413     frame.setVisible(true);
 414 
 415     Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
 416         public void run() {
 417           detachDebugger();
 418         }
 419       });
 420 
 421     // If jvmDebugger is already set, we have been given a JVMDebugger.
 422     // Otherwise, if pidText != null we are supposed to attach to it.
 423     // Finally, if execPath != null, it is the path of a jdk/bin/java
 424     // and coreFilename is the pathname of a core file we are
 425     // supposed to attach to.
 426 
 427     if (jvmDebugger != null) {
 428       attach(jvmDebugger);
 429     } else if (pidText != null) {
 430       attach(pidText);
 431     } else if (execPath != null) {
 432       attach(execPath, coreFilename);
 433     }
 434   }
 435 
 436   // FIXME: merge showAttachDialog, showOpenCoreFileDialog, showConnectDialog
 437   private void showAttachDialog() {
 438     // FIXME: create filtered text field which only accepts numbers
 439     setMenuItemsEnabled(attachMenuItems, false);
 440     final JInternalFrame attachDialog = new JInternalFrame("Attach to HotSpot process");
 441     attachDialog.getContentPane().setLayout(new BorderLayout());
 442 
 443     JPanel panel = new JPanel();
 444     panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
 445     panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
 446     attachDialog.setBackground(panel.getBackground());
 447 
 448     panel.add(new JLabel("Enter process ID:"));
 449     final JTextField pidTextField = new JTextField(10);


1114                     }
1115                   }, rm);
1116               } catch (Exception e) {
1117                 System.err.println("Error while performing oopsDo for frame " + curFrame);
1118                 e.printStackTrace();
1119               }
1120             }
1121 
1122             vf = nextVFrame;
1123           }
1124 
1125           // This used to paint as we walked the frames. This caused the display to be refreshed
1126           // enough to be annoying on remote displays. It also would cause the annotations to
1127           // be displayed in varying order which caused some annotations to overwrite others
1128           // depending on the races between painting and adding annotations. This latter problem
1129           // still exists to some degree but moving this code here definitely seems to reduce it
1130           annoPanel.makeVisible(startAddr);
1131           annoPanel.repaint();
1132         }
1133       });
1134   }
1135 
1136   // Attach to existing JVMDebugger, which should be already attached to a core/process.
1137   private void attach(JVMDebugger d) {
1138     attached = true;
1139     showThreadsDialog();
1140   }
1141 
1142   /** NOTE we are in a different thread here than either the main
1143       thread or the Swing/AWT event handler thread, so we must be very
1144       careful when creating or removing widgets */
1145   private void attach(String pidText) {
1146       try {
1147       this.pidText = pidText;
1148       pid = Integer.parseInt(pidText);
1149     }
1150     catch (NumberFormatException e) {
1151       SwingUtilities.invokeLater(new Runnable() {
1152           public void run() {
1153             setMenuItemsEnabled(attachMenuItems, true);
1154             JOptionPane.showInternalMessageDialog(desktop,
1155                                                   "Unable to parse process ID \"" + HSDB.this.pidText + "\".\nPlease enter a number.",
1156                                                   "Parse error",
1157                                                   JOptionPane.WARNING_MESSAGE);
1158           }
1159         });