Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,26 @@ public class Breakpoint implements IBreakpoint {
private int hitCount = 0;
private String condition = null;
private String logMessage = null;
private int suspendPolicy = BreakpointRequest.SUSPEND_EVENT_THREAD;
private HashMap<Object, Object> propertyMap = new HashMap<>();
private final boolean suspendAllThreads;

private boolean async = false;

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, boolean suspendAllThreads) {
this(vm, eventHub, className, lineNumber, 0, null, suspendAllThreads);
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber) {
this(vm, eventHub, className, lineNumber, 0, null);
}

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, boolean suspendAllThreads) {
this(vm, eventHub, className, lineNumber, hitCount, null, suspendAllThreads);
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount) {
this(vm, eventHub, className, lineNumber, hitCount, null);
}

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount,
String condition, boolean suspendAllThreads) {
this(vm, eventHub, className, lineNumber, hitCount, condition, null, suspendAllThreads);
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition) {
this(vm, eventHub, className, lineNumber, hitCount, condition, null);
}

Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount,
String condition, String logMessage, boolean suspendAllThreads) {
Breakpoint(VirtualMachine vm, IEventHub eventHub, String className, int lineNumber, int hitCount, String condition, String logMessage) {
this.vm = vm;
this.eventHub = eventHub;
this.suspendAllThreads = suspendAllThreads;
String contextClass = className;
String methodName = null;
String methodSignature = null;
Expand All @@ -83,15 +80,13 @@ public class Breakpoint implements IBreakpoint {
this.logMessage = logMessage;
}

Breakpoint(VirtualMachine vm, IEventHub eventHub, JavaBreakpointLocation sourceLocation, int hitCount,
String condition, String logMessage, boolean suspendAllThreads) {
Breakpoint(VirtualMachine vm, IEventHub eventHub, JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage) {
this.vm = vm;
this.eventHub = eventHub;
this.sourceLocation = sourceLocation;
this.hitCount = hitCount;
this.condition = condition;
this.logMessage = logMessage;
this.suspendAllThreads = suspendAllThreads;
}

// IDebugResource
Expand Down Expand Up @@ -209,19 +204,6 @@ public void setAsync(boolean async) {
this.async = async;
}

@Override
public void setSuspendPolicy(String policy) {
}

@Override
public String getSuspendPolicy() {
return suspendAllThreads ? "SUSPEND_ALL" : "SUSPEND_EVENT_THREAD";
}

protected boolean suspendAllThreads() {
return suspendAllThreads;
}

@Override
public CompletableFuture<IBreakpoint> install() {
// It's possible that different class loaders create new class with the same name.
Expand Down Expand Up @@ -431,11 +413,7 @@ private CompletableFuture<List<BreakpointRequest>> createBreakpointRequests(List

newLocations.forEach(location -> {
BreakpointRequest request = vm.eventRequestManager().createBreakpointRequest(location);
if ("SUSPEND_ALL".equals(getSuspendPolicy())) {
request.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);
} else {
request.setSuspendPolicy(BreakpointRequest.SUSPEND_EVENT_THREAD);
}
request.setSuspendPolicy(suspendPolicy);
if (hitCount > 0) {
request.addCountFilter(hitCount);
}
Expand Down Expand Up @@ -491,4 +469,14 @@ public void putProperty(Object key, Object value) {
public Object getProperty(Object key) {
return propertyMap.get(key);
}
}

@Override
public int getSuspendPolicy() {
return this.suspendPolicy;
}

@Override
public void setSuspendPolicy(int suspendPolicy) {
this.suspendPolicy = suspendPolicy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@ public class DebugSession implements IDebugSession {
private EventHub eventHub = new EventHub();
private List<EventRequest> eventRequests = new ArrayList<>();
private List<Disposable> subscriptions = new ArrayList<>();
private final boolean suspendAllThreads;

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

@Override
Expand Down Expand Up @@ -130,33 +127,40 @@ public void terminate() {
}

@Override
public IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage) {
return new EvaluatableBreakpoint(vm, this.getEventHub(), sourceLocation, hitCount, condition, logMessage, suspendAllThreads);
public IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage, int suspendPolicy) {
EvaluatableBreakpoint breakpoint = new EvaluatableBreakpoint(vm, this.getEventHub(), sourceLocation, hitCount, condition, logMessage);
breakpoint.setSuspendPolicy(suspendPolicy);
return breakpoint;
}

@Override
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage) {
return new EvaluatableBreakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition, logMessage, suspendAllThreads);
public IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage, int suspendPolicy) {
EvaluatableBreakpoint breakpoint = new EvaluatableBreakpoint(vm, this.getEventHub(), className, lineNumber, hitCount, condition, logMessage);
breakpoint.setSuspendPolicy(suspendPolicy);
return breakpoint;
}

@Override
public IWatchpoint createWatchPoint(String className, String fieldName, String accessType, String condition, int hitCount) {
return new Watchpoint(vm, this.getEventHub(), className, fieldName, accessType, condition, hitCount, suspendAllThreads);
return new Watchpoint(vm, this.getEventHub(), className, fieldName, accessType, condition, hitCount);
}

@Override
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught) {
setExceptionBreakpoints(notifyCaught, notifyUncaught, null, null);
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught, int suspendModeOnUncaught) {
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, null, null);
}

@Override
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] classFilters, String[] classExclusionFilters) {
setExceptionBreakpoints(notifyCaught, notifyUncaught, null, classFilters, classExclusionFilters);
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught,
int suspendModeOnUncaught, String[] classFilters, String[] classExclusionFilters) {
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught, null,
classFilters, classExclusionFilters);
}

@Override
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes,
String[] classFilters, String[] classExclusionFilters) {
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught,
int suspendModeOnUncaught, String[] exceptionTypes,
String[] classFilters, String[] classExclusionFilters) {
EventRequestManager manager = vm.eventRequestManager();

try {
Expand All @@ -172,7 +176,8 @@ public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught
subscriptions.clear();
eventRequests.clear();

// When no exception breakpoints are requested, no need to create an empty exception request.
// When no exception breakpoints are requested, no need to create an empty
// exception request.
if (notifyCaught || notifyUncaught) {
// from: https://www.javatips.net/api/REPLmode-master/src/jm/mode/replmode/REPLRunner.java
// Calling this seems to set something internally to make the
Expand All @@ -187,19 +192,8 @@ public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught
// See org.eclipse.debug.jdi.tests.AbstractJDITest for the example.

if (exceptionTypes == null || exceptionTypes.length == 0) {
ExceptionRequest request = manager.createExceptionRequest(null, notifyCaught, notifyUncaught);
request.setSuspendPolicy(suspendAllThreads ? EventRequest.SUSPEND_ALL : EventRequest.SUSPEND_EVENT_THREAD);
if (classFilters != null) {
for (String classFilter : classFilters) {
request.addClassFilter(classFilter);
}
}
if (classExclusionFilters != null) {
for (String exclusionFilter : classExclusionFilters) {
request.addClassExclusionFilter(exclusionFilter);
}
}
request.enable();
createExceptionBreakpoint(null, notifyCaught, notifyUncaught, suspendModeOnCaught,
suspendModeOnUncaught, classFilters, classExclusionFilters);
return;
}

Expand All @@ -215,31 +209,36 @@ public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught
eventRequests.add(classPrepareRequest);

Disposable subscription = eventHub.events()
.filter(debugEvent -> debugEvent.event instanceof ClassPrepareEvent
&& eventRequests.contains(debugEvent.event.request()))
.subscribe(debugEvent -> {
ClassPrepareEvent event = (ClassPrepareEvent) debugEvent.event;
createExceptionBreakpoint(event.referenceType(), notifyCaught, notifyUncaught, classFilters, classExclusionFilters);
});
.filter(debugEvent -> debugEvent.event instanceof ClassPrepareEvent
&& eventRequests.contains(debugEvent.event.request()))
.subscribe(debugEvent -> {
ClassPrepareEvent event = (ClassPrepareEvent) debugEvent.event;
createExceptionBreakpoint(event.referenceType(), notifyCaught, notifyUncaught,
suspendModeOnCaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
});
subscriptions.add(subscription);

// register exception breakpoint in the loaded classes.
for (ReferenceType refType : vm.classesByName(exceptionType)) {
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, classFilters, classExclusionFilters);
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught,
suspendModeOnUncaught, classFilters, classExclusionFilters);
}
}
}
}

@Override
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes,
public void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught,
int suspendModeOnUncaught, String[] exceptionTypes,
String[] classFilters, String[] classExclusionFilters, boolean async) {
if (async) {
AsyncJdwpUtils.runAsync(() -> {
setExceptionBreakpoints(notifyCaught, notifyUncaught, exceptionTypes, classFilters, classExclusionFilters);
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught,
exceptionTypes, classFilters, classExclusionFilters);
});
} else {
setExceptionBreakpoints(notifyCaught, notifyUncaught, exceptionTypes, classFilters, classExclusionFilters);
setExceptionBreakpoints(notifyCaught, notifyUncaught, suspendModeOnCaught, suspendModeOnUncaught,
exceptionTypes, classFilters, classExclusionFilters);
}
}

Expand All @@ -263,22 +262,27 @@ public VirtualMachine getVM() {
return vm;
}

@Override
public boolean shouldSuspendAllThreads() {
return suspendAllThreads;
}

@Override
public IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition,
int hitCount) {
return new MethodBreakpoint(vm, this.getEventHub(), className, functionName, condition, hitCount, suspendAllThreads);
return new MethodBreakpoint(vm, this.getEventHub(), className, functionName, condition, hitCount);
}

private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught,
String[] classFilters, String[] classExclusionFilters) {
int suspendModeOnCaught, int suspendModeOnUncaught, String[] classFilters, String[] classExclusionFilters) {
if (suspendModeOnCaught == suspendModeOnUncaught) {
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught, classFilters, classExclusionFilters);
} else {
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnCaught, classFilters, classExclusionFilters);
createExceptionBreakpoint(refType, notifyCaught, notifyUncaught, suspendModeOnUncaught, classFilters, classExclusionFilters);
}
}

private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaught, boolean notifyUncaught,
int suspendMode, String[] classFilters, String[] classExclusionFilters) {
EventRequestManager manager = vm.eventRequestManager();
ExceptionRequest request = manager.createExceptionRequest(refType, notifyCaught, notifyUncaught);
request.setSuspendPolicy(suspendAllThreads ? EventRequest.SUSPEND_ALL : EventRequest.SUSPEND_EVENT_THREAD);
request.setSuspendPolicy(suspendMode);
if (classFilters != null) {
for (String classFilter : classFilters) {
request.addClassFilter(classFilter);
Expand All @@ -291,4 +295,4 @@ private void createExceptionBreakpoint(ReferenceType refType, boolean notifyCaug
}
request.enable();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,14 @@ public interface IBreakpoint extends IDebugResource {

void setLogMessage(String logMessage);

int getSuspendPolicy();

void setSuspendPolicy(int suspendPolicy);

default void setAsync(boolean async) {
}

default boolean async() {
return false;
}

default void setSuspendPolicy(String policy) {
}

default String getSuspendPolicy() {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,25 @@ public interface IDebugSession {
void terminate();

// breakpoints
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage);
IBreakpoint createBreakpoint(String className, int lineNumber, int hitCount, String condition, String logMessage,
int suspendPolicy);

IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition, String logMessage);
IBreakpoint createBreakpoint(JavaBreakpointLocation sourceLocation, int hitCount, String condition,
String logMessage, int suspendPolicy);

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

void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught);
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught,
int suspendModeOnUncaught);

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

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

void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters,
boolean async);
void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, int suspendModeOnCaught,
int suspendModeOnUncaught, String[] exceptionTypes, String[] classFilters, String[] classExclusionFilters, boolean async);

IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition, int hitCount);

Expand All @@ -52,10 +57,4 @@ void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, Strin
IEventHub getEventHub();

VirtualMachine getVM();

/**
* Returns whether breakpoints should suspend all threads or just the event thread.
* This value is captured at session start and persists for the session lifetime.
*/
boolean shouldSuspendAllThreads();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import com.microsoft.java.debug.core.DebugException;
import com.microsoft.java.debug.core.protocol.Messages.Response;
import com.sun.jdi.request.EventRequest;
import com.microsoft.java.debug.core.protocol.Responses;
import com.microsoft.java.debug.core.protocol.Types;

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

return values;
}
}

public static int suspendPolicyFromBreakpointMode(String breakpointMode) {
if (Constants.SUSPEND_VM.equals(breakpointMode)) {
return EventRequest.SUSPEND_ALL;
} else if (Constants.SUSPEND_THREAD.equals(breakpointMode)) {
return EventRequest.SUSPEND_EVENT_THREAD;
}
return EventRequest.SUSPEND_EVENT_THREAD;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ public final class Constants {
public static final String PROJECT_NAME = "projectName";
public static final String DEBUGGEE_ENCODING = "debuggeeEncoding";
public static final String MAIN_CLASS = "mainClass";
}

// Breakpoint suspend modes
public static final String SUSPEND_VM = "suspendVM";
public static final String SUSPEND_THREAD = "suspendThread";
}
Loading