--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java Thu Feb 21 11:39:24 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1536 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, 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.bugspot;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import javax.swing.*;
-import javax.swing.filechooser.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.debugger.posix.*;
-import sun.jvm.hotspot.debugger.windbg.*;
-import sun.jvm.hotspot.livejvm.*;
-import sun.jvm.hotspot.memory.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.ui.*;
-import sun.jvm.hotspot.utilities.*;
-
-/** The BugSpot component. This is embeddable in an application by
- virtue of its being a JComponent. It (currently) requires the use
- of a menu bar which can be fetched via getMenuBar(). This is
- intended ultimately to replace HSDB. */
-
-public class BugSpot extends JPanel {
- public BugSpot() {
- super();
- Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
- public void run() {
- detachDebugger();
- }
- });
- }
-
- /** Turn on or off MDI (Multiple Document Interface) mode. When MDI
- is enabled, the BugSpot component contains a JDesktopPane and all
- windows are JInternalFrames. When disabled, only the menu bar is
- relevant. */
- public void setMDIMode(boolean onOrOff) {
- mdiMode = onOrOff;
- }
-
- /** Indicates whether MDI mode is enabled. */
- public boolean getMDIMode() {
- return mdiMode;
- }
-
- /** Build user interface widgets. This must be called before adding
- the BugSpot component to its parent. */
- public void build() {
- setLayout(new BorderLayout());
-
- menuBar = new JMenuBar();
-
- attachMenuItems = new java.util.ArrayList();
- detachMenuItems = new java.util.ArrayList();
- debugMenuItems = new java.util.ArrayList();
- suspendDebugMenuItems = new java.util.ArrayList();
- resumeDebugMenuItems = new java.util.ArrayList();
-
- //
- // File menu
- //
-
- JMenu menu = createMenu("File", 'F', 0);
- JMenuItem item;
- item = createMenuItem("Open source file...",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- openSourceFile();
- }
- },
- KeyEvent.VK_O, InputEvent.CTRL_MASK,
- 'O', 0);
- menu.add(item);
- detachMenuItems.add(item);
-
- menu.addSeparator();
-
- item = createMenuItem("Attach to process...",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- showAttachDialog();
- }
- },
- 'A', 0);
- menu.add(item);
- attachMenuItems.add(item);
-
- item = createMenuItem("Detach",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- detach();
- }
- },
- 'D', 0);
- menu.add(item);
- detachMenuItems.add(item);
-
- // Disable detach menu items at first
- setMenuItemsEnabled(detachMenuItems, false);
-
- menu.addSeparator();
-
- menu.add(createMenuItem("Exit",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- detach();
- System.exit(0);
- }
- },
- 'x', 1));
-
- menuBar.add(menu);
-
- //
- // Debug menu
- //
-
- debugMenu = createMenu("Debug", 'D', 0);
- item = createMenuItem("Go",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!attached) return;
- if (!isSuspended()) return;
- resume();
- }
- },
- KeyEvent.VK_F5, 0,
- 'G', 0);
- debugMenu.add(item);
- resumeDebugMenuItems.add(item);
-
- item = createMenuItem("Break",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (!attached) {
- System.err.println("Not attached");
- return;
- }
- if (isSuspended()) {
- System.err.println("Already suspended");
- return;
- }
- suspend();
- }
- },
- 'B', 0);
- debugMenu.add(item);
- suspendDebugMenuItems.add(item);
-
- debugMenu.addSeparator();
-
- item = createMenuItem("Threads...",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- showThreadsDialog();
- }
- },
- 'T', 0);
- debugMenu.add(item);
- debugMenuItems.add(item);
- // FIXME: belongs under "View -> Debug Windows"
- item = createMenuItem("Memory",
- new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- showMemoryDialog();
- }
- },
- 'M', 0);
- debugMenu.add(item);
- debugMenuItems.add(item);
-
- debugMenu.setEnabled(false);
- menuBar.add(debugMenu);
-
- if (mdiMode) {
- desktop = new JDesktopPane();
- add(desktop, BorderLayout.CENTER);
- }
-
- fixedWidthFont = GraphicsUtilities.lookupFont("Courier");
-
- debugEventTimer = new javax.swing.Timer(100, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- pollForDebugEvent();
- }
- });
- }
-
- public JMenuBar getMenuBar() {
- return menuBar;
- }
-
- public void showAttachDialog() {
- setMenuItemsEnabled(attachMenuItems, false);
- final FrameWrapper attachDialog = newFrame("Attach to process");
- attachDialog.getContentPane().setLayout(new BorderLayout());
- attachDialog.setClosable(true);
- attachDialog.setResizable(true);
-
- JPanel panel = new JPanel();
- panel.setLayout(new BorderLayout());
- panel.setBorder(GraphicsUtilities.newBorder(5));
- attachDialog.setBackground(panel.getBackground());
-
- JPanel listPanel = new JPanel();
- listPanel.setLayout(new BorderLayout());
- final ProcessListPanel plist = new ProcessListPanel(getLocalDebugger());
- panel.add(plist, BorderLayout.CENTER);
- JCheckBox check = new JCheckBox("Update list continuously");
- check.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- if (e.getStateChange() == ItemEvent.SELECTED) {
- plist.start();
- } else {
- plist.stop();
- }
- }
- });
- listPanel.add(plist, BorderLayout.CENTER);
- listPanel.add(check, BorderLayout.SOUTH);
- panel.add(listPanel, BorderLayout.CENTER);
- attachDialog.getContentPane().add(panel, BorderLayout.CENTER);
- attachDialog.setClosingActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- plist.stop();
- setMenuItemsEnabled(attachMenuItems, true);
- }
- });
-
- ActionListener attacher = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- plist.stop();
- attachDialog.setVisible(false);
- removeFrame(attachDialog);
- ProcessInfo info = plist.getSelectedProcess();
- if (info != null) {
- attach(info.getPid());
- }
- }
- };
-
- 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) {
- plist.stop();
- attachDialog.setVisible(false);
- removeFrame(attachDialog);
- setMenuItemsEnabled(attachMenuItems, true);
- }
- });
- hbox.add(button);
- hbox.add(Box.createGlue());
- panel = new JPanel();
- panel.setBorder(GraphicsUtilities.newBorder(5));
- panel.add(hbox);
-
- attachDialog.getContentPane().add(panel, BorderLayout.SOUTH);
-
- addFrame(attachDialog);
- attachDialog.pack();
- attachDialog.setSize(400, 300);
- GraphicsUtilities.centerInContainer(attachDialog.getComponent(),
- getParentDimension(attachDialog.getComponent()));
- attachDialog.setVisible(true);
- }
-
- public void showThreadsDialog() {
- final FrameWrapper threadsDialog = newFrame("Threads");
- threadsDialog.getContentPane().setLayout(new BorderLayout());
- threadsDialog.setClosable(true);
- threadsDialog.setResizable(true);
-
- ThreadListPanel threads = new ThreadListPanel(getCDebugger(), getAgent().isJavaMode());
- threads.addListener(new ThreadListPanel.Listener() {
- public void setFocus(ThreadProxy thread, JavaThread jthread) {
- setCurrentThread(thread);
- // FIXME: print this to GUI, bring some windows to foreground
- System.err.println("Focus changed to thread " + thread);
- }
- });
- threads.setBorder(GraphicsUtilities.newBorder(5));
- threadsDialog.getContentPane().add(threads);
- addFrame(threadsDialog);
- threadsDialog.pack();
- GraphicsUtilities.reshapeToAspectRatio(threadsDialog.getComponent(),
- 3.0f,
- 0.9f,
- getParentDimension(threadsDialog.getComponent()));
- GraphicsUtilities.centerInContainer(threadsDialog.getComponent(),
- getParentDimension(threadsDialog.getComponent()));
- threadsDialog.setVisible(true);
- }
-
- public void showMemoryDialog() {
- final FrameWrapper memoryDialog = newFrame("Memory");
- memoryDialog.getContentPane().setLayout(new BorderLayout());
- memoryDialog.setClosable(true);
- memoryDialog.setResizable(true);
-
- memoryDialog.getContentPane().add(new MemoryViewer(getDebugger(),
- (getDebugger().getMachineDescription().getAddressSize() == 8)),
- BorderLayout.CENTER);
- addFrame(memoryDialog);
- memoryDialog.pack();
- GraphicsUtilities.reshapeToAspectRatio(memoryDialog.getComponent(),
- 1.0f,
- 0.7f,
- getParentDimension(memoryDialog.getComponent()));
- GraphicsUtilities.centerInContainer(memoryDialog.getComponent(),
- getParentDimension(memoryDialog.getComponent()));
- memoryDialog.setVisible(true);
- }
-
- /** Changes the editor factory this debugger uses to display source
- code. Specified factory may be null, in which case the default
- factory is used. */
- public void setEditorFactory(EditorFactory fact) {
- if (fact != null) {
- editorFact = fact;
- } else {
- editorFact = new DefaultEditorFactory();
- }
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- private WorkerThread workerThread;
- private boolean mdiMode;
- private JVMDebugger localDebugger;
- private BugSpotAgent agent = new BugSpotAgent();
- private JMenuBar menuBar;
- /** List <JMenuItem> */
- private java.util.List attachMenuItems;
- private java.util.List detachMenuItems;
- private java.util.List debugMenuItems;
- private java.util.List suspendDebugMenuItems;
- private java.util.List resumeDebugMenuItems;
- private FrameWrapper stackFrame;
- private VariablePanel localsPanel;
- private StackTracePanel stackTracePanel;
- private FrameWrapper registerFrame;
- private RegisterPanel registerPanel;
- // Used for mixed-language stack traces
- private Map threadToJavaThreadMap;
-
- private JMenu debugMenu;
-
- // MDI mode only: desktop pane
- private JDesktopPane desktop;
-
- // Attach/detach state
- private boolean attached;
-
- // Suspension (combined Java/C++) state
- private boolean suspended;
-
- // Fixed-width font
- private Font fixedWidthFont;
-
- // Breakpoint setting
- // Maps Strings to List/*<LineNumberInfo>*/
- private Map sourceFileToLineNumberInfoMap;
- // Maps Strings (file names) to Sets of Integers (line numbers)
- private Map fileToBreakpointMap;
-
- // Debug events
- private javax.swing.Timer debugEventTimer;
-
- // Java debug events
- private boolean javaEventPending;
-
- static class BreakpointResult {
- private boolean success;
- private boolean set;
- private int lineNo;
- private String why;
-
- /** For positive results */
- BreakpointResult(boolean success, boolean set, int lineNo) {
- this(success, set, lineNo, null);
- }
-
- /** For negative results */
- BreakpointResult(boolean success, boolean set, int lineNo, String why) {
- this.success = success;
- this.set = set;
- this.lineNo = lineNo;
- this.why = why;
- }
-
- public boolean succeeded() {
- return success;
- }
-
- public boolean set() {
- return set;
- }
-
- /** Line at which the breakpoint was actually set; only valid if
- succeeded() returns true */
- public int getLine() {
- return lineNo;
- }
-
- public String getWhy() {
- return why;
- }
- }
-
-
- // Editors for source code. File name-to-Editor mapping.
- private Map editors;
- private EditorFactory editorFact = new DefaultEditorFactory();
- private EditorCommands editorComm = new EditorCommands() {
- public void windowClosed(Editor editor) {
- editors.remove(editor.getSourceFileName());
- }
-
- public void toggleBreakpointAtLine(Editor editor, int lineNumber) {
- // FIXME: handle "lazy" breakpoints where the source file has
- // been opened with some other mechanism (File -> Open) and we
- // don't have debug information pointing to that file yet
- // FIXME: NOT FINISHED
-
- BreakpointResult res =
- handleBreakpointToggle(editor, lineNumber);
- if (res.succeeded()) {
- if (res.set()) {
- editor.showBreakpointAtLine(res.getLine());
- } else {
- editor.clearBreakpointAtLine(res.getLine());
- }
- } else {
- String why = res.getWhy();
- if (why == null) {
- why = "";
- } else {
- why = ": " + why;
- }
- showMessageDialog("Unable to toggle breakpoint" + why,
- "Unable to toggle breakpoint",
- JOptionPane.WARNING_MESSAGE);
- }
- }
- };
-
- private void attach(final int pid) {
- try {
- getAgent().attach(pid);
- setMenuItemsEnabled(detachMenuItems, true);
- setMenuItemsEnabled(suspendDebugMenuItems, false);
- setMenuItemsEnabled(resumeDebugMenuItems, true);
- debugMenu.setEnabled(true);
- attached = true;
- suspended = true;
-
- if (getAgent().isJavaMode()) {
- System.err.println("Java HotSpot(TM) virtual machine detected.");
- } else {
- System.err.println("(No Java(TM) virtual machine detected)");
- }
-
- // Set up editor map
- editors = new HashMap();
-
- // Initialize breakpoints
- fileToBreakpointMap = new HashMap();
-
- // Create combined stack trace and local variable panel
- JPanel framePanel = new JPanel();
- framePanel.setLayout(new BorderLayout());
- framePanel.setBorder(GraphicsUtilities.newBorder(5));
- localsPanel = new VariablePanel();
- JTabbedPane tab = new JTabbedPane();
- tab.addTab("Locals", localsPanel);
- tab.setTabPlacement(JTabbedPane.BOTTOM);
- framePanel.add(tab, BorderLayout.CENTER);
- JPanel stackPanel = new JPanel();
- stackPanel.setLayout(new BoxLayout(stackPanel, BoxLayout.X_AXIS));
- stackPanel.add(new JLabel("Context:"));
- stackPanel.add(Box.createHorizontalStrut(5));
- stackTracePanel = new StackTracePanel();
- stackTracePanel.addListener(new StackTracePanel.Listener() {
- public void frameChanged(CFrame fr, JavaVFrame jfr) {
- setCurrentFrame(fr, jfr);
- }
- });
- stackPanel.add(stackTracePanel);
- framePanel.add(stackPanel, BorderLayout.NORTH);
- stackFrame = newFrame("Stack");
- stackFrame.getContentPane().setLayout(new BorderLayout());
- stackFrame.getContentPane().add(framePanel, BorderLayout.CENTER);
- stackFrame.setResizable(true);
- stackFrame.setClosable(false);
- addFrame(stackFrame);
- stackFrame.setSize(400, 200);
- GraphicsUtilities.moveToInContainer(stackFrame.getComponent(), 0.0f, 1.0f, 0, 20);
- stackFrame.setVisible(true);
-
- // Create register panel
- registerPanel = new RegisterPanel();
- registerPanel.setFont(fixedWidthFont);
- registerFrame = newFrame("Registers");
- registerFrame.getContentPane().setLayout(new BorderLayout());
- registerFrame.getContentPane().add(registerPanel, BorderLayout.CENTER);
- addFrame(registerFrame);
- registerFrame.setResizable(true);
- registerFrame.setClosable(false);
- registerFrame.setSize(225, 200);
- GraphicsUtilities.moveToInContainer(registerFrame.getComponent(),
- 1.0f, 0.0f, 0, 0);
- registerFrame.setVisible(true);
-
- resetCurrentThread();
- } catch (DebuggerException e) {
- final String errMsg = formatMessage(e.getMessage(), 80);
- setMenuItemsEnabled(attachMenuItems, true);
- showMessageDialog("Unable to connect to process ID " + pid + ":\n\n" + errMsg,
- "Unable to Connect",
- JOptionPane.WARNING_MESSAGE);
- getAgent().detach();
- }
- }
-
- private synchronized void detachDebugger() {
- if (!attached) {
- return;
- }
- if (isSuspended()) {
- resume(); // Necessary for JVMDI resumption
- }
- getAgent().detach();
- // FIXME: clear out breakpoints (both Java and C/C++) from target
- // process
- sourceFileToLineNumberInfoMap = null;
- fileToBreakpointMap = null;
- threadToJavaThreadMap = null;
- editors = null;
- attached = false;
- }
-
- private synchronized void detach() {
- detachDebugger();
- setMenuItemsEnabled(attachMenuItems, true);
- setMenuItemsEnabled(detachMenuItems, false);
- debugMenu.setEnabled(false);
- if (mdiMode) {
- // 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();
- }
- // FIXME: keep track of all windows and close them even in non-MDI
- // mode
- debugEventTimer.stop();
- }
-
- // Returns a Debugger for processes on the local machine. This is
- // only used to fetch the process list.
- private Debugger getLocalDebugger() {
- if (localDebugger == null) {
- String os = PlatformInfo.getOS();
- String cpu = PlatformInfo.getCPU();
-
- if (os.equals("win32")) {
- if (!cpu.equals("x86")) {
- throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Windows");
- }
-
- localDebugger = new WindbgDebuggerLocal(new MachineDescriptionIntelX86(), true);
- } else if (os.equals("linux")) {
- if (!cpu.equals("x86")) {
- throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Linux");
- }
-
- // FIXME: figure out how to specify path to debugger module
- throw new RuntimeException("FIXME: figure out how to specify path to debugger module");
- // localDebugger = new PosixDebuggerLocal(new MachineDescriptionIntelX86(), true);
- } else {
- // FIXME: port to Solaris
- throw new DebuggerException("Unsupported OS \"" + os + "\"");
- }
-
- // FIXME: we require that the primitive type sizes be configured
- // in order to use basic functionality in class Address such as
- // the fetching of floating-point values. There are a lot of
- // assumptions in the current code that Java floats and doubles
- // are of equivalent size to C values. The configurability of the
- // primitive type sizes hasn't seemed necessary and in this kind
- // of debugging scenario (namely, debugging arbitrary C++
- // processes) it appears difficult to support that kind of
- // flexibility.
- localDebugger.configureJavaPrimitiveTypeSizes(1, 1, 2, 8, 4, 4, 8, 2);
- }
-
- return localDebugger;
- }
-
- private BugSpotAgent getAgent() {
- return agent;
- }
-
- private Debugger getDebugger() {
- return getAgent().getDebugger();
- }
-
- private CDebugger getCDebugger() {
- return getAgent().getCDebugger();
- }
-
- private void resetCurrentThread() {
- setCurrentThread((ThreadProxy) getCDebugger().getThreadList().get(0));
- }
-
- private void setCurrentThread(ThreadProxy t) {
- // Create stack trace
- // FIXME: add ability to intermix C/Java frames
- java.util.List trace = new ArrayList();
- CFrame fr = getCDebugger().topFrameForThread(t);
- while (fr != null) {
- trace.add(new StackTraceEntry(fr, getCDebugger()));
- try {
- fr = fr.sender(t);
- } catch (AddressException e) {
- e.printStackTrace();
- showMessageDialog("Error while walking stack; stack trace will be truncated\n(see console for details)",
- "Error walking stack",
- JOptionPane.WARNING_MESSAGE);
- fr = null;
- }
- }
- JavaThread jthread = javaThreadForProxy(t);
- if (jthread != null) {
- // Java mode, and we have a Java thread.
- // Find all Java frames on the stack. We currently do this in a
- // manner which involves minimal interaction between the Java
- // and C/C++ debugging systems: any C frame which has a PC in an
- // unknown location (i.e., not in any DSO) is assumed to be a
- // Java frame. We merge stack segments of unknown frames with
- // segments of Java frames beginning with native methods.
- java.util.List javaTrace = new ArrayList();
- VFrame vf = jthread.getLastJavaVFrameDbg();
- while (vf != null) {
- if (vf.isJavaFrame()) {
- javaTrace.add(new StackTraceEntry((JavaVFrame) vf));
- vf = vf.sender();
- }
- }
- // Merge stack traces
- java.util.List mergedTrace = new ArrayList();
- int c = 0;
- int j = 0;
- while (c < trace.size()) {
- StackTraceEntry entry = (StackTraceEntry) trace.get(c);
- if (entry.isUnknownCFrame()) {
- boolean gotJavaFrame = false;
- while (j < javaTrace.size()) {
- StackTraceEntry javaEntry = (StackTraceEntry) javaTrace.get(j);
- JavaVFrame jvf = javaEntry.getJavaFrame();
- Method m = jvf.getMethod();
- if (!m.isNative() || !gotJavaFrame) {
- gotJavaFrame = true;
- mergedTrace.add(javaEntry);
- ++j;
- } else {
- break; // Reached native method; have intervening C frames
- }
- }
- if (gotJavaFrame) {
- // Skip this sequence of unknown frames, as we've
- // successfully identified it as Java frames
- while (c < trace.size() && entry.isUnknownCFrame()) {
- ++c;
- if (c < trace.size()) {
- entry = (StackTraceEntry) trace.get(c);
- }
- }
- continue;
- }
- }
- // If we get here, we either have an unknown frame we didn't
- // know how to categorize or we have a known C frame. Add it
- // to the trace.
- mergedTrace.add(entry);
- ++c;
- }
- trace = mergedTrace;
- }
- stackTracePanel.setTrace(trace);
-
- registerPanel.update(t);
- }
-
- private void setCurrentFrame(CFrame fr, JavaVFrame jfr) {
- localsPanel.clear();
-
- if (fr != null) {
- localsPanel.update(fr);
-
- // FIXME: load source file if we can find it, otherwise display disassembly
- LoadObject lo = getCDebugger().loadObjectContainingPC(fr.pc());
- if (lo != null) {
- CDebugInfoDataBase db = lo.getDebugInfoDataBase();
- if (db != null) {
- LineNumberInfo info = db.lineNumberForPC(fr.pc());
- if (info != null) {
- System.err.println("PC " + fr.pc() + ": Source file \"" +
- info.getSourceFileName() +
- "\", line number " +
- info.getLineNumber() +
- ", PC range [" +
- info.getStartPC() +
- ", " +
- info.getEndPC() +
- ")");
- // OK, here we go...
- showLineNumber(null, info.getSourceFileName(), info.getLineNumber());
- } else {
- System.err.println("(No line number information for PC " + fr.pc() + ")");
- // Dump line number information for database
- db.iterate(new LineNumberVisitor() {
- public void doLineNumber(LineNumberInfo info) {
- System.err.println(" Source file \"" +
- info.getSourceFileName() +
- "\", line number " +
- info.getLineNumber() +
- ", PC range [" +
- info.getStartPC() +
- ", " +
- info.getEndPC() +
- ")");
- }
- });
- }
- }
- }
- } else {
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(jfr != null, "Must have either C or Java frame");
- }
- localsPanel.update(jfr);
- // See whether we can locate source file and line number
- // FIXME: infer pathmap entries from user's locating of this
- // source file
- // FIXME: figure out what to do for native methods. Possible to
- // go to line number for the native method declaration?
- Method m = jfr.getMethod();
- Symbol sfn = ((InstanceKlass) m.getMethodHolder()).getSourceFileName();
- if (sfn != null) {
- int bci = jfr.getBCI();
- int lineNo = m.getLineNumberFromBCI(bci);
- if (lineNo >= 0) {
- // FIXME: show disassembly otherwise
- showLineNumber(packageName(m.getMethodHolder().getName().asString()),
- sfn.asString(), lineNo);
- }
- }
- }
- }
-
- private String packageName(String str) {
- int idx = str.lastIndexOf('/');
- if (idx < 0) {
- return "";
- }
- return str.substring(0, idx).replace('/', '.');
- }
-
- private JavaThread javaThreadForProxy(ThreadProxy t) {
- if (!getAgent().isJavaMode()) {
- return null;
- }
- if (threadToJavaThreadMap == null) {
- threadToJavaThreadMap = new HashMap();
- Threads threads = VM.getVM().getThreads();
- for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) {
- threadToJavaThreadMap.put(thr.getThreadProxy(), thr);
- }
- }
- return (JavaThread) threadToJavaThreadMap.get(t);
- }
-
- private static JMenu createMenu(String name, char mnemonic, int mnemonicPos) {
- JMenu menu = new JMenu(name);
- menu.setMnemonic(mnemonic);
- menu.setDisplayedMnemonicIndex(mnemonicPos);
- return menu;
- }
-
- private static JMenuItem createMenuItem(String name, ActionListener l) {
- JMenuItem item = new JMenuItem(name);
- item.addActionListener(l);
- return item;
- }
-
- private static JMenuItem createMenuItemInternal(String name, ActionListener l, int accelerator, int modifiers) {
- JMenuItem item = createMenuItem(name, l);
- item.setAccelerator(KeyStroke.getKeyStroke(accelerator, modifiers));
- return item;
- }
-
- private static JMenuItem createMenuItem(String name, ActionListener l, int accelerator) {
- return createMenuItemInternal(name, l, accelerator, 0);
- }
-
- private static JMenuItem createMenuItem(String name, ActionListener l, char mnemonic, int mnemonicPos) {
- JMenuItem item = createMenuItem(name, l);
- item.setMnemonic(mnemonic);
- item.setDisplayedMnemonicIndex(mnemonicPos);
- return item;
- }
-
- private static JMenuItem createMenuItem(String name,
- ActionListener l,
- int accelerator,
- int acceleratorMods,
- char mnemonic,
- int mnemonicPos) {
- JMenuItem item = createMenuItemInternal(name, l, accelerator, acceleratorMods);
- item.setMnemonic(mnemonic);
- item.setDisplayedMnemonicIndex(mnemonicPos);
- 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 static 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);
- }
- }
-
- private void showMessageDialog(final String message, final String title, final int jOptionPaneKind) {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- if (mdiMode) {
- JOptionPane.showInternalMessageDialog(desktop, message, title, jOptionPaneKind);
- } else {
- JOptionPane.showMessageDialog(null, message, title, jOptionPaneKind);
- }
- }
- });
- }
-
- private FrameWrapper newFrame(String title) {
- if (mdiMode) {
- return new JInternalFrameWrapper(new JInternalFrame(title));
- } else {
- return new JFrameWrapper(new JFrame(title));
- }
- }
-
- private void addFrame(FrameWrapper frame) {
- if (mdiMode) {
- desktop.add(frame.getComponent());
- }
- }
-
- private void removeFrame(FrameWrapper frame) {
- if (mdiMode) {
- desktop.remove(frame.getComponent());
- desktop.invalidate();
- desktop.validate();
- desktop.repaint();
- }
- // FIXME: do something when not in MDI mode
- }
-
- private Dimension getParentDimension(Component c) {
- if (mdiMode) {
- return desktop.getSize();
- } else {
- return Toolkit.getDefaultToolkit().getScreenSize();
- }
- }
-
- // Default editor implementation
- class DefaultEditor implements Editor {
- private DefaultEditorFactory factory;
- private FrameWrapper editorFrame;
- private String filename;
- private SourceCodePanel code;
- private boolean shown;
- private Object userData;
-
- public DefaultEditor(DefaultEditorFactory fact, String filename, final EditorCommands comm) {
- this.filename = filename;
- this.factory = fact;
- editorFrame = newFrame(filename);
- code = new SourceCodePanel();
- // FIXME: when font changes, change font in editors as well
- code.setFont(fixedWidthFont);
- editorFrame.getContentPane().add(code);
- editorFrame.setClosable(true);
- editorFrame.setResizable(true);
- editorFrame.setClosingActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- comm.windowClosed(DefaultEditor.this);
- removeFrame(editorFrame);
- editorFrame.dispose();
- factory.editorClosed(DefaultEditor.this);
- }
- });
- editorFrame.setActivatedActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- factory.makeEditorCurrent(DefaultEditor.this);
- code.requestFocus();
- }
- });
- code.setEditorCommands(comm, this);
- }
-
- public boolean openFile() { return code.openFile(filename); }
- public String getSourceFileName() { return filename; }
- public int getCurrentLineNumber() { return code.getCurrentLineNumber(); }
- public void showLineNumber(int lineNo) {
- if (!shown) {
- addFrame(editorFrame);
- GraphicsUtilities.reshapeToAspectRatio(editorFrame.getComponent(),
- 1.0f,
- 0.85f,
- getParentDimension(editorFrame.getComponent()));
- editorFrame.setVisible(true);
- shown = true;
- }
- code.showLineNumber(lineNo);
- editorFrame.toFront();
- }
- public void highlightLineNumber(int lineNo) { code.highlightLineNumber(lineNo); }
- public void showBreakpointAtLine(int lineNo) { code.showBreakpointAtLine(lineNo); }
- public boolean hasBreakpointAtLine(int lineNo) { return code.hasBreakpointAtLine(lineNo); }
- public void clearBreakpointAtLine(int lineNo) { code.clearBreakpointAtLine(lineNo); }
- public void clearBreakpoints() { code.clearBreakpoints(); }
- public void setUserData(Object o) { userData = o; }
- public Object getUserData() { return userData; }
- public void toFront() { editorFrame.toFront();
- factory.makeEditorCurrent(this); }
- }
-
- class DefaultEditorFactory implements EditorFactory {
- private LinkedList/*<Editor>*/ editors = new LinkedList();
-
- public Editor openFile(String filename, EditorCommands commands) {
- DefaultEditor editor = new DefaultEditor(this, filename, editorComm);
- if (!editor.openFile()) {
- return null;
- }
- return editor;
- }
-
- public Editor getCurrentEditor() {
- if (editors.isEmpty()) {
- return null;
- }
- return (Editor) editors.getFirst();
- }
-
- void editorClosed(Editor editor) {
- editors.remove(editor);
- }
-
- void makeEditorCurrent(Editor editor) {
- editors.remove(editor);
- editors.addFirst(editor);
- }
- }
-
- // Helper class for loading .java files; show only those with
- // correct file name which are also in the correct package
- static class JavaFileFilter extends javax.swing.filechooser.FileFilter {
- private String packageName;
- private String fileName;
-
- JavaFileFilter(String packageName, String fileName) {
- this.packageName = packageName;
- this.fileName = fileName;
- }
-
- public boolean accept(File f) {
- if (f.isDirectory()) {
- return true;
- }
- // This rejects most files
- if (!f.getName().equals(fileName)) {
- return false;
- }
- // Ensure selected file is in the correct package
- PackageScanner scanner = new PackageScanner();
- String pkg = scanner.scan(f);
- if (!pkg.equals(packageName)) {
- return false;
- }
- return true;
- }
-
- public String getDescription() { return "Java source files"; }
- }
-
- // Auxiliary information used only for Java source files
- static class JavaUserData {
- private String packageName; // External format
- private String sourceFileName;
-
- /** Source file name is equivalent to that found in the .java
- file; i.e., not a full path */
- JavaUserData(String packageName, String sourceFileName) {
- this.packageName = packageName;
- this.sourceFileName = sourceFileName;
- }
-
- String packageName() { return packageName; }
- String sourceFileName() { return sourceFileName; }
- }
-
- // Opens a source file. This makes it available for the setting of
- // lazy breakpoints.
- private void openSourceFile() {
- JFileChooser chooser = new JFileChooser();
- chooser.setDialogTitle("Open source code file");
- chooser.setMultiSelectionEnabled(false);
- if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) {
- return;
- }
- File chosen = chooser.getSelectedFile();
- if (chosen == null) {
- return;
- }
-
- // See whether we have a Java source file. If so, derive a package
- // name for it.
- String path = chosen.getPath();
- String name = null;
- JavaUserData data = null;
- if (path.endsWith(".java")) {
- PackageScanner scanner = new PackageScanner();
- String pkg = scanner.scan(chosen);
- // Now knowing both the package name and file name, we can put
- // this in the editor map and use it for setting breakpoints
- // later
- String fileName = chosen.getName();
- name = pkg + "." + fileName;
- data = new JavaUserData(pkg, fileName);
- } else {
- // FIXME: need pathmap mechanism
- name = path;
- }
- Editor editor = (Editor) editors.get(name);
- if (editor == null) {
- editor = editorFact.openFile(path, editorComm);
- if (editor == null) {
- showMessageDialog("Unable to open file \"" + path + "\" -- unexpected error.",
- "Unable to open file",
- JOptionPane.WARNING_MESSAGE);
- return;
- }
- editors.put(name, editor);
- if (data != null) {
- editor.setUserData(data);
- }
- } else {
- editor.toFront();
- }
- editor.showLineNumber(1);
- // Show breakpoints as well if we have any for this file
- Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName());
- if (set != null) {
- for (Iterator iter = set.iterator(); iter.hasNext(); ) {
- editor.showBreakpointAtLine(((Integer) iter.next()).intValue());
- }
- }
- }
-
- // Package name may be null, in which case the file is assumed to be
- // a C source file. Otherwise it is assumed to be a Java source file
- // and certain filtering rules will be applied.
- private void showLineNumber(String packageName, String fileName, int lineNumber) {
- String name;
- if (packageName == null) {
- name = fileName;
- } else {
- name = packageName + "." + fileName;
- }
- Editor editor = (Editor) editors.get(name);
- if (editor == null) {
- // See whether file exists
- File file = new File(fileName);
- String realFileName = fileName;
- if (!file.exists()) {
- // User must specify path to file
- JFileChooser chooser = new JFileChooser();
- chooser.setDialogTitle("Please locate " + fileName);
- chooser.setMultiSelectionEnabled(false);
- if (packageName != null) {
- chooser.setFileFilter(new JavaFileFilter(packageName, fileName));
- }
- int res = chooser.showOpenDialog(null);
- if (res != JFileChooser.APPROVE_OPTION) {
- // FIXME: show disassembly instead
- return;
- }
- // FIXME: would like to infer more from the selection; i.e.,
- // a pathmap leading up to this file
- File chosen = chooser.getSelectedFile();
- if (chosen == null) {
- return;
- }
- realFileName = chosen.getPath();
- }
- // Now instruct editor factory to open file
- editor = editorFact.openFile(realFileName, editorComm);
- if (editor == null) {
- showMessageDialog("Unable to open file \"" + realFileName + "\" -- unexpected error.",
- "Unable to open file",
- JOptionPane.WARNING_MESSAGE);
- return;
- }
- // Got an editor; put it in map
- editors.put(name, editor);
- // If Java source file, add additional information for later
- if (packageName != null) {
- editor.setUserData(new JavaUserData(packageName, fileName));
- }
- }
- // Got editor; show line
- editor.showLineNumber(lineNumber);
- editor.highlightLineNumber(lineNumber);
- // Show breakpoints as well if we have any for this file
- Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName());
- if (set != null) {
- for (Iterator iter = set.iterator(); iter.hasNext(); ) {
- editor.showBreakpointAtLine(((Integer) iter.next()).intValue());
- }
- }
- }
-
- //
- // Suspend/resume
- //
-
- private boolean isSuspended() {
- return suspended;
- }
-
- private synchronized void suspend() {
- setMenuItemsEnabled(resumeDebugMenuItems, true);
- setMenuItemsEnabled(suspendDebugMenuItems, false);
- BugSpotAgent agent = getAgent();
- if (agent.canInteractWithJava() && !agent.isJavaSuspended()) {
- agent.suspendJava();
- }
- agent.suspend();
- // FIXME: call VM.getVM().fireVMSuspended()
- resetCurrentThread();
- debugEventTimer.stop();
- suspended = true;
- }
-
- private synchronized void resume() {
- // Note: we don't wipe out the cached state like the
- // sourceFileToLineNumberInfoMap since it is too expensive to
- // recompute. Instead we recompute it if any DLLs are loaded or
- // unloaded.
- threadToJavaThreadMap = null;
- setMenuItemsEnabled(resumeDebugMenuItems, false);
- setMenuItemsEnabled(suspendDebugMenuItems, true);
- registerPanel.clear();
- // FIXME: call VM.getVM().fireVMResumed()
- BugSpotAgent agent = getAgent();
- agent.resume();
- if (agent.canInteractWithJava()) {
- if (agent.isJavaSuspended()) {
- agent.resumeJava();
- }
- if (javaEventPending) {
- javaEventPending = false;
- // Clear it out before resuming polling for events
- agent.javaEventContinue();
- }
- }
- agent.enableJavaInteraction();
- suspended = false;
- debugEventTimer.start();
- }
-
- //
- // Breakpoints
- //
-
- private synchronized BreakpointResult handleBreakpointToggle(Editor editor, int lineNumber) {
- // Currently we only use user data in editors to indicate Java
- // source files. If this changes then this code will need to
- // change.
- JavaUserData data = (JavaUserData) editor.getUserData();
- String filename = editor.getSourceFileName();
- if (data == null) {
- // C/C++ code
- // FIXME: as noted above in EditorCommands.toggleBreakpointAtLine,
- // this needs more work to handle "lazy" breakpoints in files
- // which we don't know about in the debug information yet
- CDebugger dbg = getCDebugger();
- ProcessControl prctl = dbg.getProcessControl();
- if (prctl == null) {
- return new BreakpointResult(false, false, 0, "Process control not enabled");
- }
- boolean mustSuspendAndResume = (!prctl.isSuspended());
- try {
- if (mustSuspendAndResume) {
- prctl.suspend();
- }
- // Search debug info for all DSOs
- LineNumberInfo info = getLineNumberInfo(filename, lineNumber);
- if (info != null) {
- Set bpset = (Set) fileToBreakpointMap.get(filename);
- if (bpset == null) {
- bpset = new HashSet();
- fileToBreakpointMap.put(filename, bpset);
- }
- Integer key = new Integer(info.getLineNumber());
- if (bpset.contains(key)) {
- // Clear breakpoint at this line's PC
- prctl.clearBreakpoint(info.getStartPC());
- bpset.remove(key);
- return new BreakpointResult(true, false, info.getLineNumber());
- } else {
- // Set breakpoint at this line's PC
- System.err.println("Setting breakpoint at PC " + info.getStartPC());
- prctl.setBreakpoint(info.getStartPC());
- bpset.add(key);
- return new BreakpointResult(true, true, info.getLineNumber());
- }
- } else {
- return new BreakpointResult(false, false, 0, "No debug information for this source file and line");
- }
- } finally {
- if (mustSuspendAndResume) {
- prctl.resume();
- }
- }
- } else {
- BugSpotAgent agent = getAgent();
- if (!agent.canInteractWithJava()) {
- String why;
- if (agent.isJavaInteractionDisabled()) {
- why = "Can not toggle Java breakpoints while stopped because\nof C/C++ debug events (breakpoints, single-stepping)";
- } else {
- why = "Could not talk to SA's JVMDI module to enable Java\nprogramming language breakpoints (run with -Xdebug -Xrunsa)";
- }
- return new BreakpointResult(false, false, 0, why);
- }
- Set bpset = (Set) fileToBreakpointMap.get(filename);
- if (bpset == null) {
- bpset = new HashSet();
- fileToBreakpointMap.put(filename, bpset);
- }
- boolean mustResumeAndSuspend = isSuspended();
- try {
- if (mustResumeAndSuspend) {
- agent.resume();
- }
- ServiceabilityAgentJVMDIModule.BreakpointToggleResult res =
- getAgent().toggleJavaBreakpoint(data.sourceFileName(),
- data.packageName(),
- lineNumber);
- if (res.getSuccess()) {
- Integer key = new Integer(res.getLineNumber());
- boolean addRemRes = false;
- if (res.getWasSet()) {
- addRemRes = bpset.add(key);
- System.err.println("Setting breakpoint at " + res.getMethodName() + res.getMethodSignature() +
- ", bci " + res.getBCI() + ", line " + res.getLineNumber());
- } else {
- addRemRes = bpset.remove(key);
- System.err.println("Clearing breakpoint at " + res.getMethodName() + res.getMethodSignature() +
- ", bci " + res.getBCI() + ", line " + res.getLineNumber());
- }
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(addRemRes, "Inconsistent Java breakpoint state with respect to target process");
- }
- return new BreakpointResult(true, res.getWasSet(), res.getLineNumber());
- } else {
- return new BreakpointResult(false, false, 0, res.getErrMsg());
- }
- } finally {
- if (mustResumeAndSuspend) {
- agent.suspend();
- resetCurrentThread();
- }
- }
- }
- }
-
- // Must call only when suspended
- private LineNumberInfo getLineNumberInfo(String filename, int lineNumber) {
- Map map = getSourceFileToLineNumberInfoMap();
- java.util.List infos = (java.util.List) map.get(filename);
- if (infos == null) {
- return null;
- }
- // Binary search for line number
- return searchLineNumbers(infos, lineNumber, 0, infos.size());
- }
-
- // Must call only when suspended
- private Map getSourceFileToLineNumberInfoMap() {
- if (sourceFileToLineNumberInfoMap == null) {
- // Build from debug info
- java.util.List loadObjects = getCDebugger().getLoadObjectList();
- final Map map = new HashMap();
- for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) {
- LoadObject lo = (LoadObject) iter.next();
- CDebugInfoDataBase db = lo.getDebugInfoDataBase();
- if (db != null) {
- db.iterate(new LineNumberVisitor() {
- public void doLineNumber(LineNumberInfo info) {
- String name = info.getSourceFileName();
- if (name != null) {
- java.util.List val = (java.util.List) map.get(name);
- if (val == null) {
- val = new ArrayList();
- map.put(name, val);
- }
- val.add(info);
- }
- }
- });
- }
- }
- // Sort all lists
- for (Iterator iter = map.values().iterator(); iter.hasNext(); ) {
- java.util.List list = (java.util.List) iter.next();
- Collections.sort(list, new Comparator() {
- public int compare(Object o1, Object o2) {
- LineNumberInfo l1 = (LineNumberInfo) o1;
- LineNumberInfo l2 = (LineNumberInfo) o2;
- int n1 = l1.getLineNumber();
- int n2 = l2.getLineNumber();
- if (n1 < n2) return -1;
- if (n1 == n2) return 0;
- return 1;
- }
- });
- }
- sourceFileToLineNumberInfoMap = map;
- }
- return sourceFileToLineNumberInfoMap;
- }
-
- private LineNumberInfo searchLineNumbers(java.util.List infoList, int lineNo, int lowIdx, int highIdx) {
- if (highIdx < lowIdx) return null;
- if (lowIdx == highIdx) {
- // Base case: see whether start PC is less than or equal to addr
- if (checkLineNumber(infoList, lineNo, lowIdx)) {
- return (LineNumberInfo) infoList.get(lowIdx);
- } else {
- return null;
- }
- } else if (lowIdx == highIdx - 1) {
- if (checkLineNumber(infoList, lineNo, lowIdx)) {
- return (LineNumberInfo) infoList.get(lowIdx);
- } else if (checkLineNumber(infoList, lineNo, highIdx)) {
- return (LineNumberInfo) infoList.get(highIdx);
- } else {
- return null;
- }
- }
- int midIdx = (lowIdx + highIdx) >> 1;
- LineNumberInfo info = (LineNumberInfo) infoList.get(midIdx);
- if (lineNo < info.getLineNumber()) {
- // Always move search down
- return searchLineNumbers(infoList, lineNo, lowIdx, midIdx);
- } else if (lineNo == info.getLineNumber()) {
- return info;
- } else {
- // Move search up
- return searchLineNumbers(infoList, lineNo, midIdx, highIdx);
- }
- }
-
- private boolean checkLineNumber(java.util.List infoList, int lineNo, int idx) {
- LineNumberInfo info = (LineNumberInfo) infoList.get(idx);
- return (info.getLineNumber() >= lineNo);
- }
-
- //
- // Debug events
- //
-
- private synchronized void pollForDebugEvent() {
- ProcessControl prctl = getCDebugger().getProcessControl();
- if (prctl == null) {
- return;
- }
- DebugEvent ev = prctl.debugEventPoll();
- if (ev != null) {
- DebugEvent.Type t = ev.getType();
- if (t == DebugEvent.Type.LOADOBJECT_LOAD ||
- t == DebugEvent.Type.LOADOBJECT_UNLOAD) {
- // Conservatively clear cached debug info state
- sourceFileToLineNumberInfoMap = null;
- // FIXME: would be very useful to have "stop on load/unload"
- // events
- // FIXME: must do work at these events to implement lazy
- // breakpoints
- prctl.debugEventContinue();
- } else if (t == DebugEvent.Type.BREAKPOINT) {
- // Note: Visual C++ only notifies on breakpoints it doesn't
- // know about
-
- // FIXME: put back test
- // if (!prctl.isBreakpointSet(ev.getPC())) {
- showMessageDialog("Breakpoint reached at PC " + ev.getPC(),
- "Breakpoint reached",
- JOptionPane.INFORMATION_MESSAGE);
- // }
- agent.disableJavaInteraction();
- suspend();
- prctl.debugEventContinue();
- } else if (t == DebugEvent.Type.SINGLE_STEP) {
- agent.disableJavaInteraction();
- suspend();
- prctl.debugEventContinue();
- } else if (t == DebugEvent.Type.ACCESS_VIOLATION) {
- showMessageDialog("Access violation attempting to " +
- (ev.getWasWrite() ? "write" : "read") +
- " address " + ev.getAddress() +
- " at PC " + ev.getPC(),
- "Access Violation",
- JOptionPane.WARNING_MESSAGE);
- agent.disableJavaInteraction();
- suspend();
- prctl.debugEventContinue();
- } else {
- String info = "Unknown debug event encountered";
- if (ev.getUnknownEventDetail() != null) {
- info = info + ": " + ev.getUnknownEventDetail();
- }
- showMessageDialog(info, "Unknown debug event", JOptionPane.INFORMATION_MESSAGE);
- suspend();
- prctl.debugEventContinue();
- }
- return;
- }
-
- // No C++ debug event; poll for Java debug event
- if (getAgent().canInteractWithJava()) {
- if (!javaEventPending) {
- if (getAgent().javaEventPending()) {
- suspend();
- // This does a lot of work and we want to have the page
- // cache available to us as it runs
- sun.jvm.hotspot.livejvm.Event jev = getAgent().javaEventPoll();
- if (jev != null) {
- javaEventPending = true;
- if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.BREAKPOINT) {
- BreakpointEvent bpev = (BreakpointEvent) jev;
- showMessageDialog("Breakpoint reached in method\n" +
- bpev.methodID().method().externalNameAndSignature() +
- ",\nbci " + bpev.location(),
- "Breakpoint reached",
- JOptionPane.INFORMATION_MESSAGE);
- } else if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.EXCEPTION) {
- ExceptionEvent exev = (ExceptionEvent) jev;
- showMessageDialog(exev.exception().getKlass().getName().asString() +
- "\nthrown in method\n" +
- exev.methodID().method().externalNameAndSignature() +
- "\nat BCI " + exev.location(),
- "Exception thrown",
- JOptionPane.INFORMATION_MESSAGE);
- } else {
- Assert.that(false, "Should not reach here");
- }
- }
- }
- }
- }
- }
-}