Skip to content

Commit 247face

Browse files
committed
Add suspend mode for source breakpoints
1 parent 31dd8ee commit 247face

File tree

13 files changed

+324
-126
lines changed

13 files changed

+324
-126
lines changed

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/Breakpoint.java

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,29 +41,26 @@ public class Breakpoint implements IBreakpoint {
4141
private int hitCount = 0;
4242
private String condition = null;
4343
private String logMessage = null;
44+
private int suspendPolicy = BreakpointRequest.SUSPEND_EVENT_THREAD;
4445
private HashMap<Object, Object> propertyMap = new HashMap<>();
45-
private final boolean suspendAllThreads;
4646

4747
private boolean async = false;
4848

49-
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, boolean suspendAllThreads) {
50-
this(vm, eventHub, className, lineNumber, 0, null, suspendAllThreads);
49+
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber) {
50+
this(vm, eventHub, className, lineNumber, 0, null);
5151
}
5252

53-
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, boolean suspendAllThreads) {
54-
this(vm, eventHub, className, lineNumber, hitCount, null, suspendAllThreads);
53+
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount) {
54+
this(vm, eventHub, className, lineNumber, hitCount, null);
5555
}
5656

57-
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount,
58-
String condition, boolean suspendAllThreads) {
59-
this(vm, eventHub, className, lineNumber, hitCount, condition, null, suspendAllThreads);
57+
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition) {
58+
this(vm, eventHub, className, lineNumber, hitCount, condition, null);
6059
}
6160

62-
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount,
63-
String condition, String logMessage, boolean suspendAllThreads) {
61+
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition, String logMessage) {
6462
this.vm = vm;
6563
this.eventHub = eventHub;
66-
this.suspendAllThreads = suspendAllThreads;
6764
String contextClass = className;
6865
String methodName = null;
6966
String methodSignature = null;
@@ -83,15 +80,13 @@ public class Breakpoint implements IBreakpoint {
8380
this.logMessage = logMessage;
8481
}
8582

86-
Breakpoint(VirtualMachine vm, IEventHub eventHub, JavaBreakpointLocation sourceLocation, int hitCount,
87-
String condition, String logMessage, boolean suspendAllThreads) {
83+
Breakpoint(VirtualMachine vm, IEventHub eventHub, JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage) {
8884
this.vm = vm;
8985
this.eventHub = eventHub;
9086
this.sourceLocation = sourceLocation;
9187
this.hitCount = hitCount;
9288
this.condition = condition;
9389
this.logMessage = logMessage;
94-
this.suspendAllThreads = suspendAllThreads;
9590
}
9691

9792
// IDebugResource
@@ -209,19 +204,6 @@ public void setAsync(boolean async) {
209204
this.async = async;
210205
}
211206

212-
@Override
213-
public void setSuspendPolicy(String policy) {
214-
}
215-
216-
@Override
217-
public String getSuspendPolicy() {
218-
return suspendAllThreads ? "SUSPEND_ALL" : "SUSPEND_EVENT_THREAD";
219-
}
220-
221-
protected boolean suspendAllThreads() {
222-
return suspendAllThreads;
223-
}
224-
225207
@Override
226208
public CompletableFuture<IBreakpoint> install() {
227209
// It's possible that different class loaders create new class with the same name.
@@ -431,11 +413,7 @@ private CompletableFuture<List<BreakpointRequest>> createBreakpointRequests(List
431413

432414
newLocations.forEach(location -> {
433415
BreakpointRequest request = vm.eventRequestManager().createBreakpointRequest(location);
434-
if ("SUSPEND_ALL".equals(getSuspendPolicy())) {
435-
request.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);
436-
} else {
437-
request.setSuspendPolicy(BreakpointRequest.SUSPEND_EVENT_THREAD);
438-
}
416+
request.setSuspendPolicy(suspendPolicy);
439417
if (hitCount > 0) {
440418
request.addCountFilter(hitCount);
441419
}
@@ -491,4 +469,14 @@ public void putProperty(Object key, Object value) {
491469
public Object getProperty(Object key) {
492470
return propertyMap.get(key);
493471
}
494-
}
472+
473+
@Override
474+
public int getSuspendPolicy() {
475+
return this.suspendPolicy;
476+
}
477+
478+
@Override
479+
public void setSuspendPolicy(int suspendPolicy) {
480+
this.suspendPolicy = suspendPolicy;
481+
}
482+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,9 @@ public class DebugSession implements IDebugSession {
3636
private EventHub eventHub = new EventHub();
3737
private List<EventRequest> eventRequests = new ArrayList<>();
3838
private List<Disposable> subscriptions = new ArrayList<>();
39-
private final boolean suspendAllThreads;
4039

4140
public DebugSession(VirtualMachine virtualMachine) {
4241
vm = virtualMachine;
43-
// Capture suspend policy at session start - this persists for the session lifetime
44-
this.suspendAllThreads = DebugSettings.getCurrent().suspendAllThreads;
4542
}
4643

4744
@Override
@@ -130,32 +127,36 @@ public void terminate() {
130127
}
131128

132129
@Override
133-
public IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage) {
134-
return new EvaluatableBreakpoint(vm, this.getEventHub(), sourceLocation, hitCount, condition, logMessage, suspendAllThreads);
130+
public IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage, int suspendPolicy) {
131+
EvaluatableBreakpoint breakpoint = new EvaluatableBreakpoint(vm, this.getEventHub(), sourceLocation, hitCount, condition, logMessage);
132+
breakpoint.setSuspendPolicy(suspendPolicy);
133+
return breakpoint;
135134
}
136135

137136
@Override
138-
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage) {
139-
return new EvaluatableBreakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition, logMessage, suspendAllThreads);
137+
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage, int suspendPolicy) {
138+
EvaluatableBreakpoint breakpoint = new EvaluatableBreakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition, logMessage);
139+
breakpoint.setSuspendPolicy(suspendPolicy);
140+
return breakpoint;
140141
}
141142

142143
@Override
143144
public IWatchpoint createWatchPoint(String className, String fieldName, String accessType, String condition, int hitCount) {
144-
return new Watchpoint(vm, this.getEventHub(), className, fieldName, accessType, condition, hitCount, suspendAllThreads);
145+
return new Watchpoint(vm, this.getEventHub(), className, fieldName, accessType, condition, hitCount);
145146
}
146147

147148
@Override
148-
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught) {
149-
setExceptionBreakpoints(notifyCaught, notifyUncaught, null, null);
149+
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught) {
150+
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, null, null);
150151
}
151152

152153
@Override
153-
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] classFilters, String[] classExclusionFilters) {
154-
setExceptionBreakpoints(notifyCaught, notifyUncaught, null, classFilters, classExclusionFilters);
154+
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] classFilters, String[] classExclusionFilters) {
155+
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, null, classFilters, classExclusionFilters);
155156
}
156157

157158
@Override
158-
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes,
159+
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] exceptionTypes,
159160
String[] classFilters, String[] classExclusionFilters) {
160161
EventRequestManager manager = vm.eventRequestManager();
161162

@@ -187,19 +188,7 @@ public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught
187188
// See org.eclipse.debug.jdi.tests.AbstractJDITest for the example.
188189

189190
if (exceptionTypes == null || exceptionTypes.length == 0) {
190-
ExceptionRequest request = manager.createExceptionRequest(null, notifyCaught, notifyUncaught);
191-
request.setSuspendPolicy(suspendAllThreads ? EventRequest.SUSPEND_ALL : EventRequest.SUSPEND_EVENT_THREAD);
192-
if (classFilters != null) {
193-
for (String classFilter : classFilters) {
194-
request.addClassFilter(classFilter);
195-
}
196-
}
197-
if (classExclusionFilters != null) {
198-
for (String exclusionFilter : classExclusionFilters) {
199-
request.addClassExclusionFilter(exclusionFilter);
200-
}
201-
}
202-
request.enable();
191+
createExceptionBreakpoint(null, notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
203192
return;
204193
}
205194

@@ -219,27 +208,27 @@ public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught
219208
&& eventRequests.contains(debugEvent.event.request()))
220209
.subscribe(debugEvent -> {
221210
ClassPrepareEvent event = (ClassPrepareEvent) debugEvent.event;
222-
createExceptionBreakpoint(event.referenceType(), notifyCaught, notifyUncaught, classFilters, classExclusionFilters);
211+
createExceptionBreakpoint(event.referenceType(), notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
223212
});
224213
subscriptions.add(subscription);
225214

226215
// register exception breakpoint in the loaded classes.
227216
for (ReferenceType refType : vm.classesByName(exceptionType)) {
228-
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, classFilters, classExclusionFilters);
217+
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
229218
}
230219
}
231220
}
232221
}
233222

234223
@Override
235-
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes,
224+
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] exceptionTypes,
236225
String[] classFilters, String[] classExclusionFilters, boolean async) {
237226
if (async) {
238227
AsyncJdwpUtils.runAsync(() -> {
239-
setExceptionBreakpoints(notifyCaught, notifyUncaught, exceptionTypes, classFilters, classExclusionFilters);
228+
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, exceptionTypes, classFilters, classExclusionFilters);
240229
});
241230
} else {
242-
setExceptionBreakpoints(notifyCaught, notifyUncaught, exceptionTypes, classFilters, classExclusionFilters);
231+
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, exceptionTypes, classFilters, classExclusionFilters);
243232
}
244233
}
245234

@@ -263,22 +252,27 @@ public VirtualMachine getVM() {
263252
return vm;
264253
}
265254

266-
@Override
267-
public boolean shouldSuspendAllThreads() {
268-
return suspendAllThreads;
269-
}
270-
271255
@Override
272256
public IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition,
273257
int hitCount) {
274-
return new MethodBreakpoint(vm, this.getEventHub(), className, functionName, condition, hitCount, suspendAllThreads);
258+
return new MethodBreakpoint(vm, this.getEventHub(), className, functionName, condition, hitCount);
259+
}
260+
261+
private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught,
262+
int suspendModeOnCaught, int suspendModeOnUncaught, String[] classFilters, String[] classExclusionFilters) {
263+
if (suspendModeOnCaught == suspendModeOnUncaught) {
264+
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught, classFilters, classExclusionFilters);
265+
} else {
266+
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught, classFilters, classExclusionFilters);
267+
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
268+
}
275269
}
276270

277271
private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught,
278-
String[] classFilters, String[] classExclusionFilters) {
272+
int suspendMode, String[] classFilters, String[] classExclusionFilters) {
279273
EventRequestManager manager = vm.eventRequestManager();
280274
ExceptionRequest request = manager.createExceptionRequest(refType, notifyCaught, notifyUncaught);
281-
request.setSuspendPolicy(suspendAllThreads ? EventRequest.SUSPEND_ALL : EventRequest.SUSPEND_EVENT_THREAD);
275+
request.setSuspendPolicy(suspendMode);
282276
if (classFilters != null) {
283277
for (String classFilter : classFilters) {
284278
request.addClassFilter(classFilter);
@@ -291,4 +285,4 @@ private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaug
291285
}
292286
request.enable();
293287
}
294-
}
288+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IBreakpoint.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,14 @@ public interface IBreakpoint extends IDebugResource {
4949

5050
void setLogMessage(String logMessage);
5151

52+
int getSuspendPolicy();
53+
54+
void setSuspendPolicy(int suspendPolicy);
55+
5256
default void setAsync(boolean async) {
5357
}
5458

5559
default boolean async() {
5660
return false;
5761
}
58-
59-
default void setSuspendPolicy(String policy) {
60-
}
61-
62-
default String getSuspendPolicy() {
63-
return null;
64-
}
65-
}
62+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IDebugSession.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ public interface IDebugSession {
2828
void terminate();
2929

3030
// breakpoints
31-
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage);
31+
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage, int suspendPolicy);
3232

33-
IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage);
33+
IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage, int suspendPolicy);
3434

3535
IWatchpoint createWatchPoint(String className, String fieldName, String accessType, String condition, int hitCount);
3636

37-
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught);
37+
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught);
3838

39-
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] classFilters, String[] classExclusionFilters);
39+
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] classFilters, String[] classExclusionFilters);
4040

41-
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters);
41+
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters);
4242

43-
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters,
43+
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters,
4444
boolean async);
4545

4646
IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition, int hitCount);
@@ -52,10 +52,4 @@ void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, Strin
5252
IEventHub getEventHub();
5353

5454
VirtualMachine getVM();
55-
56-
/**
57-
* Returns whether breakpoints should suspend all threads or just the event thread.
58-
* This value is captured at session start and persists for the session lifetime.
59-
*/
60-
boolean shouldSuspendAllThreads();
61-
}
55+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/AdapterUtils.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import com.microsoft.java.debug.core.DebugException;
3636
import com.microsoft.java.debug.core.protocol.Messages.Response;
37+
import com.sun.jdi.request.EventRequest;
3738
import com.microsoft.java.debug.core.protocol.Responses;
3839
import com.microsoft.java.debug.core.protocol.Types;
3940

@@ -364,4 +365,13 @@ public static int[] binarySearchMappedLines(int[] lineMappings, int targetLine)
364365

365366
return values;
366367
}
367-
}
368+
369+
public static int suspendPolicyFromBreakpointMode(String breakpointMode) {
370+
if (Constants.SUSPEND_VM.equals(breakpointMode)) {
371+
return EventRequest.SUSPEND_ALL;
372+
} else if (Constants.SUSPEND_THREAD.equals(breakpointMode)) {
373+
return EventRequest.SUSPEND_EVENT_THREAD;
374+
}
375+
return EventRequest.SUSPEND_EVENT_THREAD;
376+
}
377+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/Constants.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ public final class Constants {
1515
public static final String PROJECT_NAME = "projectName";
1616
public static final String DEBUGGEE_ENCODING = "debuggeeEncoding";
1717
public static final String MAIN_CLASS = "mainClass";
18-
}
18+
19+
// Breakpoint suspend modes
20+
public static final String SUSPEND_VM = "suspendVM";
21+
public static final String SUSPEND_THREAD = "suspendThread";
22+
}

com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/ConfigurationDoneRequestHandler.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
import com.sun.jdi.event.ThreadStartEvent;
4141
import com.sun.jdi.event.VMDeathEvent;
4242
import com.sun.jdi.event.VMDisconnectEvent;
43-
import com.sun.jdi.request.EventRequest;
4443
import com.sun.jdi.event.VMStartEvent;
44+
import com.sun.jdi.request.EventRequest;
4545

4646
public class ConfigurationDoneRequestHandler implements IDebugRequestHandler {
4747
protected static final Logger logger = Logger.getLogger(Configuration.LOGGER_NAME);
@@ -120,9 +120,8 @@ private void handleDebugEvent(DebugEvent debugEvent, IDebugSession debugSession,
120120
((ExceptionEvent) event).catchLocation() == null);
121121
context.getExceptionManager().setException(thread.uniqueID(), jdiException);
122122
context.getThreadCache().addEventThread(thread, "exception");
123-
boolean allThreadsStopped = event.request() != null
124-
&& event.request().suspendPolicy() == EventRequest.SUSPEND_ALL;
125-
context.getProtocolServer().sendEvent(new Events.StoppedEvent("exception", thread.uniqueID(), allThreadsStopped));
123+
boolean suspendAll = event.request() != null ? event.request().suspendPolicy() == EventRequest.SUSPEND_ALL : false;
124+
context.getProtocolServer().sendEvent(new Events.StoppedEvent("exception", thread.uniqueID(), suspendAll));
126125
debugEvent.shouldResume = false;
127126
} else {
128127
isImportantEvent = false;
@@ -133,4 +132,4 @@ private void handleDebugEvent(DebugEvent debugEvent, IDebugSession debugSession,
133132
UsageDataSession.recordEvent(event);
134133
}
135134
}
136-
}
135+
}

0 commit comments

Comments
 (0)