diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index b9a017ba75e1..cb13f6b67b60 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -44,7 +44,6 @@ import com.sun.jdi.VMDisconnectedException; import com.sun.jdi.VirtualMachine; import com.sun.jdi.event.*; import com.sun.jdi.request.EventRequest; -import com.sun.jdi.request.MethodExitRequest; /** * @author lex @@ -133,7 +132,7 @@ public class DebugProcessEvents extends DebugProcessImpl { while (!isStopped()) { try { final EventSet eventSet = eventQueue.remove(); - if (myReturnValueWatcher != null && myReturnValueWatcher.isTrackingEnabled()) { + if (myReturnValueWatcher != null && myReturnValueWatcher.isEnabled()) { int processed = 0; for (EventIterator eventIterator = eventSet.eventIterator(); eventIterator.hasNext();) { final Event event = eventIterator.nextEvent(); @@ -264,9 +263,7 @@ public class DebugProcessEvents extends DebugProcessImpl { if(myState.compareAndSet(STATE_INITIAL, STATE_ATTACHED)) { final VirtualMachineProxyImpl machineProxy = getVirtualMachineProxy(); if (machineProxy.canGetMethodReturnValues()) { - MethodExitRequest request = machineProxy.eventRequestManager().createMethodExitRequest(); - request.setSuspendPolicy(EventRequest.SUSPEND_NONE); - myReturnValueWatcher = new MethodReturnValueWatcher(request); + myReturnValueWatcher = new MethodReturnValueWatcher(machineProxy.eventRequestManager()); } DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager().setInitialBreakpointsState(); @@ -310,7 +307,7 @@ public class DebugProcessEvents extends DebugProcessImpl { } private void processStepEvent(SuspendContextImpl suspendContext, StepEvent event) { - ThreadReference thread = event.thread(); + final ThreadReference thread = event.thread(); //LOG.assertTrue(thread.isSuspended()); preprocessEvent(suspendContext, thread); @@ -340,7 +337,7 @@ public class DebugProcessEvents extends DebugProcessImpl { else { showStatusText(""); if (myReturnValueWatcher != null) { - myReturnValueWatcher.setTrackingEnabled(false); + myReturnValueWatcher.disable(); } getSuspendManager().voteSuspend(suspendContext); } @@ -404,7 +401,7 @@ public class DebugProcessEvents extends DebugProcessImpl { } else { if (myReturnValueWatcher != null) { - myReturnValueWatcher.setTrackingEnabled(false); + myReturnValueWatcher.disable(); } if (suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL) { // there could be explicit resume as a result of call to voteSuspend() diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index d933dca6b60b..eeab0654ca1a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1383,7 +1383,7 @@ public abstract class DebugProcessImpl implements DebugProcess { RequestHint hint = new RequestHint(thread, suspendContext, StepRequest.STEP_OUT); hint.setIgnoreFilters(mySession.shouldIgnoreSteppingFilters()); if (myReturnValueWatcher != null) { - myReturnValueWatcher.setTrackingEnabled(true); + myReturnValueWatcher.enable(thread.getThreadReference()); } doStep(suspendContext, thread, StepRequest.STEP_OUT, hint); super.contextAction(); @@ -1441,7 +1441,7 @@ public abstract class DebugProcessImpl implements DebugProcess { hint.setIgnoreFilters(myIsIgnoreBreakpoints || mySession.shouldIgnoreSteppingFilters()); if (myReturnValueWatcher != null) { - myReturnValueWatcher.setTrackingEnabled(true); + myReturnValueWatcher.enable(steppingThread.getThreadReference()); } doStep(suspendContext, steppingThread, StepRequest.STEP_OVER, hint); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java index d0acd7f9704a..d56c31ec757e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java @@ -20,10 +20,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.ArrayUtil; import com.sun.jdi.Method; import com.sun.jdi.ObjectCollectedException; +import com.sun.jdi.ThreadReference; import com.sun.jdi.Value; import com.sun.jdi.event.MethodExitEvent; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.EventRequestManager; import com.sun.jdi.request.MethodExitRequest; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.InvocationTargetException; @@ -36,19 +38,19 @@ public class MethodReturnValueWatcher { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.requests.MethodReturnValueWatcher"); private @Nullable Method myLastExecutedMethod; private @Nullable Value myLastMethodReturnValue; - private @NotNull final MethodExitRequest myWatchMethodReturnValueRequest; + private @Nullable MethodExitRequest myRequest; private java.lang.reflect.Method myReturnValueMethod; - private volatile boolean myIsTrackingEnabled; + private volatile boolean myEnabled; private boolean myFeatureEnabled; + private final EventRequestManager myRequestManager; - public MethodReturnValueWatcher(final MethodExitRequest request) { - myWatchMethodReturnValueRequest = request; - myIsTrackingEnabled = request.isEnabled(); + public MethodReturnValueWatcher(EventRequestManager requestManager) { + myRequestManager = requestManager; myFeatureEnabled = DebuggerSettings.getInstance().WATCH_RETURN_VALUES; } public boolean processMethodExitEvent(MethodExitEvent event) { - if (event.request() != myWatchMethodReturnValueRequest) { + if (event.request() != myRequest) { return false; } try { @@ -95,38 +97,54 @@ public class MethodReturnValueWatcher { return myFeatureEnabled; } - public boolean isTrackingEnabled() { - return myIsTrackingEnabled; + public boolean isEnabled() { + return myEnabled; } public void setFeatureEnabled(final boolean featureEnabled) { myFeatureEnabled = featureEnabled; - updateRequestState(featureEnabled && myIsTrackingEnabled); myLastExecutedMethod = null; myLastMethodReturnValue = null; } - public void setTrackingEnabled(boolean trackingEnabled) { - myIsTrackingEnabled = trackingEnabled; - updateRequestState(trackingEnabled && myFeatureEnabled); + public void enable(ThreadReference thread) { + setTrackingEnabled(true, thread); + } + + public void disable() { + setTrackingEnabled(false, null); + } + + private void setTrackingEnabled(boolean trackingEnabled, final ThreadReference thread) { + myEnabled = trackingEnabled; + updateRequestState(trackingEnabled && myFeatureEnabled, thread); } - private void updateRequestState(final boolean enabled) { + private void updateRequestState(final boolean enabled, @Nullable final ThreadReference thread) { try { + final MethodExitRequest request = myRequest; + if (request != null) { + myRequest = null; + myRequestManager.deleteEventRequest(request); + } if (enabled) { myLastExecutedMethod = null; myLastMethodReturnValue = null; - if (!myWatchMethodReturnValueRequest.isEnabled()) { - myWatchMethodReturnValueRequest.enable(); - } - } - else { - if (myWatchMethodReturnValueRequest.isEnabled()) { - myWatchMethodReturnValueRequest.disable(); - } + myRequest = createRequest(thread); + myRequest.enable(); } } catch (ObjectCollectedException ignored) { } } + + private MethodExitRequest createRequest(@Nullable final ThreadReference thread) { + final MethodExitRequest request = myRequestManager.createMethodExitRequest(); + request.setSuspendPolicy(EventRequest.SUSPEND_NONE); + if (thread != null) { + request.addThreadFilter(thread); + } + return request; + } + }