From 795a6eba8d19d91047f10b37165870969a157b8a Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Mon, 29 Apr 2013 10:05:03 -0400 Subject: [PATCH] use JVMTI, remove extra thread suspend calls, remove unused --- app/.classpath | 2 +- .../mode/java/runner/EventThread.java | 409 ------------------ .../processing/mode/java/runner/Runner.java | 74 +--- 3 files changed, 18 insertions(+), 467 deletions(-) delete mode 100644 app/src/processing/mode/java/runner/EventThread.java diff --git a/app/.classpath b/app/.classpath index 0e855598d..eb8980d92 100644 --- a/app/.classpath +++ b/app/.classpath @@ -1,6 +1,6 @@ - + diff --git a/app/src/processing/mode/java/runner/EventThread.java b/app/src/processing/mode/java/runner/EventThread.java deleted file mode 100644 index e613bfbcc..000000000 --- a/app/src/processing/mode/java/runner/EventThread.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * @(#)EventThread.java 1.4 03/01/23 - * - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ -/* - * Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved. - * - * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, - * modify and redistribute this software in source and binary code form, - * provided that i) this copyright notice and license appear on all copies of - * the software; and ii) Licensee does not utilize the software in a manner - * which is disparaging to Sun. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY - * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR - * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE - * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING - * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS - * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, - * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER - * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF - * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - * - * This software is not designed or intended for use in on-line control of - * aircraft, air traffic, aircraft navigation or aircraft communications; or in - * the design, construction, operation or maintenance of any nuclear - * facility. Licensee represents and warrants that it will not use or - * redistribute the Software for such purposes. - */ - -package processing.mode.java.runner; - -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; -import com.sun.jdi.request.*; - -/** - * This class processes incoming JDI events and displays them - * - * @version @(#) EventThread.java 1.4 03/01/23 23:33:38 - * @author Robert Field - */ -public class EventThread extends Thread { - - private final Runner parent; - private final VirtualMachine vm; // Running VM - private final String[] excludes; // Packages to exclude - private final PrintWriter writer; // Where output goes - - static String nextBaseIndent = ""; // Starting indent for next thread - - private boolean connected = true; // Connected to VM - private boolean vmDied = true; // VMDeath occurred - - // Maps ThreadReference to ThreadTrace instances - private Map traceMap = new HashMap(); - - - public EventThread(Runner parent, VirtualMachine vm, String[] excludes, PrintWriter writer) { - super("event-handler"); - this.parent = parent; - this.vm = vm; - this.excludes = excludes; - this.writer = writer; - } - - /** - * Run the event handling thread. - * As long as we are connected, get event sets off - * the queue and dispatch the events within them. - */ - public void run() { - EventQueue queue = vm.eventQueue(); -// setEventRequests(false); // ATTEMPT TO MOVE HERE 130427 - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator it = eventSet.eventIterator(); - while (it.hasNext()) { - handleEvent(it.nextEvent()); - } - eventSet.resume(); - } catch (InterruptedException exc) { - // Ignore - } catch (VMDisconnectedException discExc) { - handleDisconnectedException(); - break; - } - } - } - - /** - * Create the desired event requests, and enable - * them so that we will get events. - * @param excludes Class patterns for which we don't want events - * @param watchFields Do we want to watch assignments to fields - */ - public void setEventRequests(boolean watchFields) { - EventRequestManager mgr = vm.eventRequestManager(); - -// VMDeathRequest deathReq = mgr.createVMDeathRequest(); -// deathReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); -// deathReq.enable(); - - // get only the uncaught exceptions - ExceptionRequest excReq = mgr.createExceptionRequest(null, false, true); - // this version reports all exceptions, caught or uncaught -// ExceptionRequest excReq = mgr.createExceptionRequest(null, true, true); - // suspend so we can step - excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); -// excReq.setSuspendPolicy(EventRequest.SUSPEND_NONE); // another option? - excReq.enable(); - - /* - MethodEntryRequest menr = mgr.createMethodEntryRequest(); - for (int i=0; i 0) { - indent.append("| "); - } - - EventRequestManager mgr = vm.eventRequestManager(); - mgr.deleteEventRequest(event.request()); - } - - void threadDeathEvent(ThreadDeathEvent event) { - indent = new StringBuffer(baseIndent); - println("====== " + thread.name() + " end ======"); - } - } - - /** - * Returns the ThreadTrace instance for the specified thread, - * creating one if needed. - */ - ThreadTrace threadTrace(ThreadReference thread) { - ThreadTrace trace = (ThreadTrace)traceMap.get(thread); - if (trace == null) { - trace = new ThreadTrace(thread); - traceMap.put(thread, trace); - } - return trace; - } - - /** - * Dispatch incoming events - */ - private void handleEvent(Event event) { - System.out.println("EventThread.handleEvent -> " + event); - if (event instanceof ExceptionEvent) { - exceptionEvent((ExceptionEvent)event); - } else if (event instanceof ModificationWatchpointEvent) { - fieldWatchEvent((ModificationWatchpointEvent)event); - } else if (event instanceof MethodEntryEvent) { - methodEntryEvent((MethodEntryEvent)event); - } else if (event instanceof MethodExitEvent) { - methodExitEvent((MethodExitEvent)event); - } else if (event instanceof StepEvent) { - stepEvent((StepEvent)event); - } else if (event instanceof ThreadDeathEvent) { - threadDeathEvent((ThreadDeathEvent)event); - } else if (event instanceof ClassPrepareEvent) { - classPrepareEvent((ClassPrepareEvent)event); - } else if (event instanceof VMStartEvent) { - vmStartEvent((VMStartEvent)event); - } else if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } else { - throw new Error("Unexpected event type"); - } - } - - /*** - * A VMDisconnectedException has happened while dealing with - * another event. We need to flush the event queue, dealing only - * with exit events (VMDeath, VMDisconnect) so that we terminate - * correctly. - */ - synchronized void handleDisconnectedException() { - EventQueue queue = vm.eventQueue(); - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator iter = eventSet.eventIterator(); - while (iter.hasNext()) { - Event event = iter.nextEvent(); - if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } - } - eventSet.resume(); // Resume the VM - } catch (InterruptedException exc) { - // ignore - } - } - } - - private void vmStartEvent(VMStartEvent event) { - if (writer != null) writer.println("-- VM Started --"); - } - - // Forward event for thread specific processing - private void methodEntryEvent(MethodEntryEvent event) { - threadTrace(event.thread()).methodEntryEvent(event); - } - - // Forward event for thread specific processing - private void methodExitEvent(MethodExitEvent event) { - threadTrace(event.thread()).methodExitEvent(event); - } - - // Forward event for thread specific processing - private void stepEvent(StepEvent event) { - threadTrace(event.thread()).stepEvent(event); - } - - // Forward event for thread specific processing - private void fieldWatchEvent(ModificationWatchpointEvent event) { - threadTrace(event.thread()).fieldWatchEvent(event); - } - - void threadDeathEvent(ThreadDeathEvent event) { - ThreadTrace trace = (ThreadTrace)traceMap.get(event.thread()); - if (trace != null) { // only want threads we care about - trace.threadDeathEvent(event); // Forward event - } - } - - /** - * A new class has been loaded. - * Set watchpoints on each of its fields - */ - private void classPrepareEvent(ClassPrepareEvent event) { -// System.out.println(event); -// List list = event.referenceType().methodsByName("stop"); -// Object o = list.get(0); -// System.out.println("stop methods = " + list); -// System.out.println(o.getClass()); - - EventRequestManager mgr = vm.eventRequestManager(); - List fields = event.referenceType().visibleFields(); - for (Iterator it = fields.iterator(); it.hasNext(); ) { - Field field = (Field)it.next(); - ModificationWatchpointRequest req = - mgr.createModificationWatchpointRequest(field); - for (int i=0; i " + event); - /*if (event instanceof VMStartEvent) { -// for (ThreadReference thread : vm.allThreads()) { -// System.out.println("thread: " + thread); -// } - // Calling this seems to set something internally to make the - // Eclipse JDI wake up. Without it, an ObjectCollectedException - // is thrown on excReq.enable(). No idea why this works, - // but at least exception handling has returned. - vm.allThreads(); - - EventRequestManager mgr = vm.eventRequestManager(); - // get only the uncaught exceptions - ExceptionRequest excReq = mgr.createExceptionRequest(null, false, true); -// System.out.println(excReq); - // this version reports all exceptions, caught or uncaught -// ExceptionRequest excReq = mgr.createExceptionRequest(null, true, true); - // suspend so we can step - excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); -// excReq.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); -// excReq.setSuspendPolicy(EventRequest.SUSPEND_NONE); // another option? - excReq.enable(); - - } else*/ if (event instanceof ExceptionEvent) { + if (event instanceof ExceptionEvent) { for (ThreadReference thread : vm.allThreads()) { thread.suspend(); } @@ -727,7 +700,6 @@ public class Runner implements MessageConsumer { connected = false; } } - // for (Event e : eventSet) { System.out.println("VM Event: " + e.toString()); } } // } catch (VMDisconnectedException e) { // Logger.getLogger(VMEventReader.class.getName()).log(Level.INFO, "VMEventReader quit on VM disconnect"); @@ -740,25 +712,13 @@ public class Runner implements MessageConsumer { }; eventThread.start(); - //redirectOutput(); + + errThread = + new MessageSiphon(process.getErrorStream(), this).getThread(); -// Process process = vm.process(); -// Process process = javaProcess; - -// processInput = new SystemOutSiphon(process.getInputStream()); -// processError = new MessageSiphon(process.getErrorStream(), this); - - // Copy target's output and error to our output and error. -// errThread = new StreamRedirectThread("error reader", -// process.getErrorStream(), -// System.err); - MessageSiphon ms = new MessageSiphon(process.getErrorStream(), this); - errThread = ms.getThread(); - - outThread = new StreamRedirectThread("output reader", + outThread = new StreamRedirectThread("JVM stdout Reader", process.getInputStream(), System.out); - errThread.start(); outThread.start();