/* * Copyright (c) 1998, 2008, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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 com.sun.tools.example.debug.bdi; import com.sun.jdi.*;import com.sun.jdi.request.*;import com.sun.jdi.connect.*;import com.sun.tools.example.debug.expr.ExpressionParser;import com.sun.tools.example.debug.expr.ParseException; import java.io.*;import java.util.*; import com.sun.tools.example.debug.event.*; import javax.swing.SwingUtilities; /** * Move this towards being only state and functionality * that spans across Sessions (and thus VMs). */public class ExecutionManager { private Session session; /** * Get/set JDI trace mode. */ int traceMode = VirtualMachine.TRACE_NONE; ////////////////// Listener registration ////////////////// // Session Listeners ArrayList<SessionListener> sessionListeners = new ArrayList<SessionListener>(); public void addSessionListener(SessionListener listener) { sessionListeners.add(listener); } public void removeSessionListener(SessionListener listener) { sessionListeners.remove(listener); } // Spec Listeners ArrayList<SpecListener> specListeners = new ArrayList<SpecListener>(); public void addSpecListener(SpecListener cl) { specListeners.add(cl); } public void removeSpecListener(SpecListener cl) { specListeners.remove(cl); } // JDI Listeners ArrayList<JDIListener> jdiListeners = new ArrayList<JDIListener>(); /** * Adds a JDIListener */ public void addJDIListener(JDIListener jl) { jdiListeners.add(jl); } /** * Adds a JDIListener - at the specified position */ public void addJDIListener(int index, JDIListener jl) { jdiListeners.add(index, jl); } /** * Removes a JDIListener */ public void removeJDIListener(JDIListener jl) { jdiListeners.remove(jl); } // App Echo Listeners private ArrayList<OutputListener> appEchoListeners = new ArrayList<OutputListener>(); public void addApplicationEchoListener(OutputListener l) { appEchoListeners.add(l); } public void removeApplicationEchoListener(OutputListener l) { appEchoListeners.remove(l); } // App Output Listeners private ArrayList<OutputListener> appOutputListeners = new ArrayList<OutputListener>(); public void addApplicationOutputListener(OutputListener l) { appOutputListeners.add(l); } public void removeApplicationOutputListener(OutputListener l) { appOutputListeners.remove(l); } // App Error Listeners private ArrayList<OutputListener> appErrorListeners = new ArrayList<OutputListener>(); public void addApplicationErrorListener(OutputListener l) { appErrorListeners.add(l); } public void removeApplicationErrorListener(OutputListener l) { appErrorListeners.remove(l); } // Diagnostic Listeners private ArrayList<OutputListener> diagnosticsListeners = new ArrayList<OutputListener>(); public void addDiagnosticsListener(OutputListener l) { diagnosticsListeners.add(l); } public void removeDiagnosticsListener(OutputListener l) { diagnosticsListeners.remove(l); } /////////// End Listener Registration ////////////// //### We probably don't want this public public VirtualMachine vm() { return session == null ? null : session.vm; } void ensureActiveSession() throws NoSessionException { if (session == null) { throw new NoSessionException(); } } public EventRequestManager eventRequestManager() { return vm() == null ? null : vm().eventRequestManager(); } /** * Get JDI trace mode. */ public int getTraceMode(int mode) { return traceMode; } /** * Set JDI trace mode. */ public void setTraceMode(int mode) { traceMode = mode; if (session != null) { session.setTraceMode(mode); } } /** * Determine if VM is interrupted, i.e, present and not running. */ public boolean isInterrupted() /* should: throws NoSessionException */ {// ensureActiveSession(); return session.interrupted; } /** * Return a list of ReferenceType objects for all * currently loaded classes and interfaces. * Array types are not returned. */ public List<ReferenceType> allClasses() throws NoSessionException { ensureActiveSession(); return vm().allClasses(); } /** * Return a ReferenceType object for the currently * loaded class or interface whose fully-qualified * class name is specified, else return null if there * is none. * * In general, we must return a list of types, because * multiple class loaders could have loaded a class * with the same fully-qualified name. */ public List<ReferenceType> findClassesByName(String name) throws NoSessionException { ensureActiveSession(); return vm().classesByName(name); } /** * Return a list of ReferenceType objects for all * currently loaded classes and interfaces whose name * matches the given pattern. The pattern syntax is * open to some future revision, but currently consists * of a fully-qualified class name in which the first * component may optionally be a "*" character, designating * an arbitrary prefix. */ public List<ReferenceType> findClassesMatchingPattern(String pattern) throws NoSessionException { ensureActiveSession(); List<ReferenceType> result = new ArrayList<ReferenceType>(); //### Is default size OK? if (pattern.startsWith("*.")) { // Wildcard matches any leading package name. pattern = pattern.substring(1); for (ReferenceType type : vm().allClasses()) { if (type.name().endsWith(pattern)) { result.add(type); } } return result; } else { // It's a class name. return vm().classesByName(pattern); } } /* * Return a list of ThreadReference objects corresponding * to the threads that are currently active in the VM. * A thread is removed from the list just before the * thread terminates. */ public List<ThreadReference> allThreads() throws NoSessionException { ensureActiveSession(); return vm().allThreads(); } /* * Return a list of ThreadGroupReference objects corresponding * to the top-level threadgroups that are currently active in the VM. * Note that a thread group may be empty, or contain no threads as * descendents. */ public List<ThreadGroupReference> topLevelThreadGroups() throws NoSessionException { ensureActiveSession(); return vm().topLevelThreadGroups(); } /* * Return the system threadgroup. */ public ThreadGroupReference systemThreadGroup() throws NoSessionException { ensureActiveSession(); return vm().topLevelThreadGroups().get(0); } /* * Evaluate an expression. */ public Value evaluate(final StackFrame f, String expr) throws ParseException, InvocationException, InvalidTypeException, ClassNotLoadedException, NoSessionException, IncompatibleThreadStateException { ExpressionParser.GetFrame frameGetter = null; ensureActiveSession(); if (f != null) { frameGetter = new ExpressionParser.GetFrame() { @Override public StackFrame get() /* throws IncompatibleThreadStateException */ { return f; } }; } return ExpressionParser.evaluate(expr, vm(), frameGetter); } /* * Start a new VM. */ public void run(boolean suspended, String vmArgs, String className, String args) throws VMLaunchFailureException { endSession(); //### Set a breakpoint on 'main' method. //### Would be cleaner if we could just bring up VM already suspended. if (suspended) { //### Set breakpoint at 'main(java.lang.String[])'. List<String> argList = new ArrayList<String>(1); argList.add("java.lang.String[]"); createMethodBreakpoint(className, "main", argList); } String cmdLine = className + " " + args; startSession(new ChildSession(this, vmArgs, cmdLine, appInput, appOutput, appError, diagnostics)); } /* * Attach to an existing VM. */ public void attach(String portName) throws VMLaunchFailureException { endSession(); //### Changes made here for connectors have broken the //### the 'Session' abstraction. The 'Session.attach()' //### method is intended to encapsulate all of the various //### ways in which session start-up can fail. (maddox 12/18/98) /* * Now that attaches and launches both go through Connectors, * it may be worth creating a new subclass of Session for * attach sessions. */ VirtualMachineManager mgr = Bootstrap.virtualMachineManager(); AttachingConnector connector = mgr.attachingConnectors().get(0); Map<String, Connector.Argument> arguments = connector.defaultArguments(); arguments.get("port").setValue(portName); Session newSession = internalAttach(connector, arguments); if (newSession != null) { startSession(newSession); } } private Session internalAttach(AttachingConnector connector, Map<String, Connector.Argument> arguments) { try { VirtualMachine vm = connector.attach(arguments); return new Session(vm, this, diagnostics); } catch (IOException ioe) { diagnostics.putString("\n Unable to attach to target VM: " + ioe.getMessage()); } catch (IllegalConnectorArgumentsException icae) { diagnostics.putString("\n Invalid connector arguments: " + icae.getMessage()); } return null; } private Session internalListen(ListeningConnector connector, Map<String, Connector.Argument> arguments) { try { VirtualMachine vm = connector.accept(arguments); return new Session(vm, this, diagnostics); } catch (IOException ioe) { diagnostics.putString( "\n Unable to accept connection to target VM: " + ioe.getMessage()); } catch (IllegalConnectorArgumentsException icae) { diagnostics.putString("\n Invalid connector arguments: " + icae.getMessage()); } return null; } /* * Connect via user specified arguments * @return true on success */ public boolean explictStart(Connector connector, Map<String, Connector.Argument> arguments) throws VMLaunchFailureException { Session newSession = null; endSession(); if (connector instanceof LaunchingConnector) { // we were launched, use ChildSession newSession = new ChildSession(this, (LaunchingConnector)connector, arguments, appInput, appOutput, appError, diagnostics); } else if (connector instanceof AttachingConnector) { newSession = internalAttach((AttachingConnector)connector, arguments); } else if (connector instanceof ListeningConnector) { newSession = internalListen((ListeningConnector)connector, arguments); } else { diagnostics.putString("\n Unknown connector: " + connector); } if (newSession != null) { startSession(newSession); } return newSession != null; } /* * Detach from VM. If VM was started by debugger, terminate it. */ public void detach() throws NoSessionException { ensureActiveSession(); endSession(); } private void startSession(Session s) throws VMLaunchFailureException { if (!s.attach()) { throw new VMLaunchFailureException(); } session = s; EventRequestManager em = vm().eventRequestManager(); ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest(); //### We must allow the deferred breakpoints to be resolved before //### we continue executing the class. We could optimize if there //### were no deferred breakpoints outstanding for a particular class. //### Can we do this with JDI? classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); classPrepareRequest.enable(); ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest(); classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); classUnloadRequest.enable(); ThreadStartRequest threadStartRequest = em.createThreadStartRequest(); threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); threadStartRequest.enable(); ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest(); threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); threadDeathRequest.enable(); ExceptionRequest exceptionRequest = em.createExceptionRequest(null, false, true); exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); exceptionRequest.enable(); validateThreadInfo(); session.interrupted = true; notifySessionStart(); } void endSession() { if (session != null) { session.detach(); session = null; invalidateThreadInfo(); notifySessionDeath(); } } /* * Suspend all VM activity. */ public void interrupt() throws NoSessionException { ensureActiveSession(); vm().suspend(); //### Is it guaranteed that the interrupt has happened? validateThreadInfo(); session.interrupted = true; notifyInterrupted(); } /* * Resume interrupted VM. */ public void go() throws NoSessionException, VMNotInterruptedException { ensureActiveSession(); invalidateThreadInfo(); session.interrupted = false; notifyContinued(); vm().resume(); } /* * Stepping. */ void clearPreviousStep(ThreadReference thread) { /*Lines 1–500 of 815. Load more
/* * Copyright (c) 1998, 2008, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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 com.sun.tools.example.debug.bdi; import com.sun.jdi.*; import com.sun.jdi.request.*; import com.sun.jdi.connect.*; import com.sun.tools.example.debug.expr.ExpressionParser; import com.sun.tools.example.debug.expr.ParseException; import java.io.*; import java.util.*; import com.sun.tools.example.debug.event.*; import javax.swing.SwingUtilities; /** * Move this towards being only state and functionality * that spans across Sessions (and thus VMs). */ public class ExecutionManager { private Session session; /** * Get/set JDI trace mode. */ int traceMode = VirtualMachine.TRACE_NONE; ////////////////// Listener registration ////////////////// // Session Listeners ArrayList<SessionListener> sessionListeners = new ArrayList<SessionListener>(); public void addSessionListener(SessionListener listener) { sessionListeners.add(listener); } public void removeSessionListener(SessionListener listener) { sessionListeners.remove(listener); } // Spec Listeners ArrayList<SpecListener> specListeners = new ArrayList<SpecListener>(); public void addSpecListener(SpecListener cl) { specListeners.add(cl); } public void removeSpecListener(SpecListener cl) { specListeners.remove(cl); } // JDI Listeners ArrayList<JDIListener> jdiListeners = new ArrayList<JDIListener>(); /** * Adds a JDIListener */ public void addJDIListener(JDIListener jl) { jdiListeners.add(jl); } /** * Adds a JDIListener - at the specified position */ public void addJDIListener(int index, JDIListener jl) { jdiListeners.add(index, jl); } /** * Removes a JDIListener */ public void removeJDIListener(JDIListener jl) { jdiListeners.remove(jl); } // App Echo Listeners private ArrayList<OutputListener> appEchoListeners = new ArrayList<OutputListener>(); public void addApplicationEchoListener(OutputListener l) { appEchoListeners.add(l); } public void removeApplicationEchoListener(OutputListener l) { appEchoListeners.remove(l); } // App Output Listeners private ArrayList<OutputListener> appOutputListeners = new ArrayList<OutputListener>(); public void addApplicationOutputListener(OutputListener l) { appOutputListeners.add(l); } public void removeApplicationOutputListener(OutputListener l) { appOutputListeners.remove(l); } // App Error Listeners private ArrayList<OutputListener> appErrorListeners = new ArrayList<OutputListener>(); public void addApplicationErrorListener(OutputListener l) { appErrorListeners.add(l); } public void removeApplicationErrorListener(OutputListener l) { appErrorListeners.remove(l); } // Diagnostic Listeners private ArrayList<OutputListener> diagnosticsListeners = new ArrayList<OutputListener>(); public void addDiagnosticsListener(OutputListener l) { diagnosticsListeners.add(l); } public void removeDiagnosticsListener(OutputListener l) { diagnosticsListeners.remove(l); } /////////// End Listener Registration ////////////// //### We probably don't want this public public VirtualMachine vm() { return session == null ? null : session.vm; } void ensureActiveSession() throws NoSessionException { if (session == null) { throw new NoSessionException(); } } public EventRequestManager eventRequestManager() { return vm() == null ? null : vm().eventRequestManager(); } /** * Get JDI trace mode. */ public int getTraceMode(int mode) { return traceMode; } /** * Set JDI trace mode. */ public void setTraceMode(int mode) { traceMode = mode; if (session != null) { session.setTraceMode(mode); } } /** * Determine if VM is interrupted, i.e, present and not running. */ public boolean isInterrupted() /* should: throws NoSessionException */ { // ensureActiveSession(); return session.interrupted; } /** * Return a list of ReferenceType objects for all * currently loaded classes and interfaces. * Array types are not returned. */ public List<ReferenceType> allClasses() throws NoSessionException { ensureActiveSession(); return vm().allClasses(); } /** * Return a ReferenceType object for the currently * loaded class or interface whose fully-qualified * class name is specified, else return null if there * is none. * * In general, we must return a list of types, because * multiple class loaders could have loaded a class * with the same fully-qualified name. */ public List<ReferenceType> findClassesByName(String name) throws NoSessionException { ensureActiveSession(); return vm().classesByName(name); } /** * Return a list of ReferenceType objects for all * currently loaded classes and interfaces whose name * matches the given pattern. The pattern syntax is * open to some future revision, but currently consists * of a fully-qualified class name in which the first * component may optionally be a "*" character, designating * an arbitrary prefix. */ public List<ReferenceType> findClassesMatchingPattern(String pattern) throws NoSessionException { ensureActiveSession(); List<ReferenceType> result = new ArrayList<ReferenceType>(); //### Is default size OK? if (pattern.startsWith("*.")) { // Wildcard matches any leading package name. pattern = pattern.substring(1); for (ReferenceType type : vm().allClasses()) { if (type.name().endsWith(pattern)) { result.add(type); } } return result; } else { // It's a class name. return vm().classesByName(pattern); } } /* * Return a list of ThreadReference objects corresponding * to the threads that are currently active in the VM. * A thread is removed from the list just before the * thread terminates. */ public List<ThreadReference> allThreads() throws NoSessionException { ensureActiveSession(); return vm().allThreads(); } /* * Return a list of ThreadGroupReference objects corresponding * to the top-level threadgroups that are currently active in the VM. * Note that a thread group may be empty, or contain no threads as * descendents. */ public List<ThreadGroupReference> topLevelThreadGroups() throws NoSessionException { ensureActiveSession(); return vm().topLevelThreadGroups(); } /* * Return the system threadgroup. */ public ThreadGroupReference systemThreadGroup() throws NoSessionException { ensureActiveSession(); return vm().topLevelThreadGroups().get(0); } /* * Evaluate an expression. */ public Value evaluate(final StackFrame f, String expr) throws ParseException, InvocationException, InvalidTypeException, ClassNotLoadedException, NoSessionException, IncompatibleThreadStateException { ExpressionParser.GetFrame frameGetter = null; ensureActiveSession(); if (f != null) { frameGetter = new ExpressionParser.GetFrame() { @Override public StackFrame get() /* throws IncompatibleThreadStateException */ { return f; } }; } return ExpressionParser.evaluate(expr, vm(), frameGetter); } /* * Start a new VM. */ public void run(boolean suspended, String vmArgs, String className, String args) throws VMLaunchFailureException { endSession(); //### Set a breakpoint on 'main' method. //### Would be cleaner if we could just bring up VM already suspended. if (suspended) { //### Set breakpoint at 'main(java.lang.String[])'. List<String> argList = new ArrayList<String>(1); argList.add("java.lang.String[]"); createMethodBreakpoint(className, "main", argList); } String cmdLine = className + " " + args; startSession(new ChildSession(this, vmArgs, cmdLine, appInput, appOutput, appError, diagnostics)); } /* * Attach to an existing VM. */ public void attach(String portName) throws VMLaunchFailureException { endSession(); //### Changes made here for connectors have broken the //### the 'Session' abstraction. The 'Session.attach()' //### method is intended to encapsulate all of the various //### ways in which session start-up can fail. (maddox 12/18/98) /* * Now that attaches and launches both go through Connectors, * it may be worth creating a new subclass of Session for * attach sessions. */ VirtualMachineManager mgr = Bootstrap.virtualMachineManager(); AttachingConnector connector = mgr.attachingConnectors().get(0); Map<String, Connector.Argument> arguments = connector.defaultArguments(); arguments.get("port").setValue(portName); Session newSession = internalAttach(connector, arguments); if (newSession != null) { startSession(newSession); } } private Session internalAttach(AttachingConnector connector, Map<String, Connector.Argument> arguments) { try { VirtualMachine vm = connector.attach(arguments); return new Session(vm, this, diagnostics); } catch (IOException ioe) { diagnostics.putString("\n Unable to attach to target VM: " + ioe.getMessage()); } catch (IllegalConnectorArgumentsException icae) { diagnostics.putString("\n Invalid connector arguments: " + icae.getMessage()); } return null; } private Session internalListen(ListeningConnector connector, Map<String, Connector.Argument> arguments) { try { VirtualMachine vm = connector.accept(arguments); return new Session(vm, this, diagnostics); } catch (IOException ioe) { diagnostics.putString( "\n Unable to accept connection to target VM: " + ioe.getMessage()); } catch (IllegalConnectorArgumentsException icae) { diagnostics.putString("\n Invalid connector arguments: " + icae.getMessage()); } return null; } /* * Connect via user specified arguments * @return true on success */ public boolean explictStart(Connector connector, Map<String, Connector.Argument> arguments) throws VMLaunchFailureException { Session newSession = null; endSession(); if (connector instanceof LaunchingConnector) { // we were launched, use ChildSession newSession = new ChildSession(this, (LaunchingConnector)connector, arguments, appInput, appOutput, appError, diagnostics); } else if (connector instanceof AttachingConnector) { newSession = internalAttach((AttachingConnector)connector, arguments); } else if (connector instanceof ListeningConnector) { newSession = internalListen((ListeningConnector)connector, arguments); } else { diagnostics.putString("\n Unknown connector: " + connector); } if (newSession != null) { startSession(newSession); } return newSession != null; } /* * Detach from VM. If VM was started by debugger, terminate it. */ public void detach() throws NoSessionException { ensureActiveSession(); endSession(); } private void startSession(Session s) throws VMLaunchFailureException { if (!s.attach()) { throw new VMLaunchFailureException(); } session = s; EventRequestManager em = vm().eventRequestManager(); ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest(); //### We must allow the deferred breakpoints to be resolved before //### we continue executing the class. We could optimize if there //### were no deferred breakpoints outstanding for a particular class. //### Can we do this with JDI? classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); classPrepareRequest.enable(); ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest(); classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); classUnloadRequest.enable(); ThreadStartRequest threadStartRequest = em.createThreadStartRequest(); threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); threadStartRequest.enable(); ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest(); threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); threadDeathRequest.enable(); ExceptionRequest exceptionRequest = em.createExceptionRequest(null, false, true); exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); exceptionRequest.enable(); validateThreadInfo(); session.interrupted = true; notifySessionStart(); } void endSession() { if (session != null) { session.detach(); session = null; invalidateThreadInfo(); notifySessionDeath(); } } /* * Suspend all VM activity. */ public void interrupt() throws NoSessionException { ensureActiveSession(); vm().suspend(); //### Is it guaranteed that the interrupt has happened? validateThreadInfo(); session.interrupted = true; notifyInterrupted(); } /* * Resume interrupted VM. */ public void go() throws NoSessionException, VMNotInterruptedException { ensureActiveSession(); invalidateThreadInfo(); session.interrupted = false; notifyContinued(); vm().resume(); } /* * Stepping. */ void clearPreviousStep(ThreadReference thread) { /*