Skip to content

Commit e6fae9c

Browse files
Fix perf issue when debugging pet clinic with "stopOnEntry" on (microsoft#115)
* Fix perf issue when debugging pet clinic with "stopOnEntry" on Signed-off-by: Jinbo Wang <jinbwan@microsoft.com> * eat the VMDisconnectedException silently when deleteEventRequest Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
1 parent 9110089 commit e6fae9c

2 files changed

Lines changed: 73 additions & 22 deletions

File tree

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.commons.lang3.StringUtils;
2626

2727
import com.sun.jdi.Location;
28+
import com.sun.jdi.Method;
2829
import com.sun.jdi.ObjectCollectedException;
2930
import com.sun.jdi.ThreadReference;
3031
import com.sun.jdi.VMDisconnectedException;
@@ -35,8 +36,11 @@
3536
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
3637
import com.sun.jdi.connect.LaunchingConnector;
3738
import com.sun.jdi.connect.VMStartException;
39+
import com.sun.jdi.event.MethodEntryEvent;
3840
import com.sun.jdi.event.StepEvent;
3941
import com.sun.jdi.request.EventRequest;
42+
import com.sun.jdi.request.EventRequestManager;
43+
import com.sun.jdi.request.MethodEntryRequest;
4044
import com.sun.jdi.request.StepRequest;
4145

4246
public class DebugUtility {
@@ -240,7 +244,7 @@ private static CompletableFuture<Location> step(ThreadReference thread, IEventHu
240244
.subscribe(debugEvent -> {
241245
StepEvent event = (StepEvent) debugEvent.event;
242246
future.complete(event.location());
243-
thread.virtualMachine().eventRequestManager().deleteEventRequest(request);
247+
deleteEventRequestSafely(thread.virtualMachine().eventRequestManager(), request);
244248
});
245249
request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
246250
request.addCountFilter(1);
@@ -251,6 +255,40 @@ private static CompletableFuture<Location> step(ThreadReference thread, IEventHu
251255
return future;
252256
}
253257

258+
/**
259+
* Suspend the main thread when the program enters the main method of the specified main class.
260+
* @param debugSession
261+
* the debug session.
262+
* @param mainClass
263+
* the fully qualified name of the main class.
264+
* @return
265+
* a {@link CompletableFuture} that contains the suspended main thread id.
266+
*/
267+
public static CompletableFuture<Long> stopOnEntry(IDebugSession debugSession, String mainClass) {
268+
CompletableFuture<Long> future = new CompletableFuture<>();
269+
270+
EventRequestManager manager = debugSession.getVM().eventRequestManager();
271+
MethodEntryRequest request = manager.createMethodEntryRequest();
272+
request.addClassFilter(mainClass);
273+
request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
274+
275+
debugSession.getEventHub().events().filter(debugEvent -> {
276+
return debugEvent.event instanceof MethodEntryEvent && request.equals(debugEvent.event.request());
277+
}).subscribe(debugEvent -> {
278+
Method method = ((MethodEntryEvent) debugEvent.event).method();
279+
if (method.isPublic() && method.isStatic() && method.name().equals("main")
280+
&& method.signature().equals("([Ljava/lang/String;)V")) {
281+
deleteEventRequestSafely(debugSession.getVM().eventRequestManager(), request);
282+
debugEvent.shouldResume = false;
283+
ThreadReference bpThread = ((MethodEntryEvent) debugEvent.event).thread();
284+
future.complete(bpThread.uniqueID());
285+
}
286+
});
287+
request.enable();
288+
289+
return future;
290+
}
291+
254292
/**
255293
* Get the ThreadReference instance by the thread id.
256294
* @param debugSession
@@ -312,6 +350,36 @@ public static void resumeThread(ThreadReference thread) {
312350
}
313351
}
314352

353+
/**
354+
* Remove the event request from the vm. If the vm has terminated, do nothing.
355+
* @param eventManager
356+
* The event request manager.
357+
* @param request
358+
* The target event request.
359+
*/
360+
public static void deleteEventRequestSafely(EventRequestManager eventManager, EventRequest request) {
361+
try {
362+
eventManager.deleteEventRequest(request);
363+
} catch (VMDisconnectedException ex) {
364+
// ignore.
365+
}
366+
}
367+
368+
/**
369+
* Remove the event request list from the vm. If the vm has terminated, do nothing.
370+
* @param eventManager
371+
* The event request manager.
372+
* @param requests
373+
* The target event request list.
374+
*/
375+
public static void deleteEventRequestSafely(EventRequestManager eventManager, List<EventRequest> requests) {
376+
try {
377+
eventManager.deleteEventRequests(requests);
378+
} catch (VMDisconnectedException ex) {
379+
// ignore.
380+
}
381+
}
382+
315383
/**
316384
* Encode an string array to a string as the follows.
317385
*

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

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.concurrent.CompletableFuture;
1717

1818
import com.microsoft.java.debug.core.DebugEvent;
19+
import com.microsoft.java.debug.core.DebugUtility;
1920
import com.microsoft.java.debug.core.IDebugSession;
2021
import com.microsoft.java.debug.core.UsageDataSession;
2122
import com.microsoft.java.debug.core.adapter.AdapterUtils;
@@ -26,21 +27,16 @@
2627
import com.microsoft.java.debug.core.protocol.Messages.Response;
2728
import com.microsoft.java.debug.core.protocol.Requests.Arguments;
2829
import com.microsoft.java.debug.core.protocol.Requests.Command;
29-
import com.sun.jdi.Method;
3030
import com.sun.jdi.ThreadReference;
3131
import com.sun.jdi.event.BreakpointEvent;
3232
import com.sun.jdi.event.Event;
3333
import com.sun.jdi.event.ExceptionEvent;
34-
import com.sun.jdi.event.MethodEntryEvent;
3534
import com.sun.jdi.event.StepEvent;
3635
import com.sun.jdi.event.ThreadDeathEvent;
3736
import com.sun.jdi.event.ThreadStartEvent;
3837
import com.sun.jdi.event.VMDeathEvent;
3938
import com.sun.jdi.event.VMDisconnectEvent;
4039
import com.sun.jdi.event.VMStartEvent;
41-
import com.sun.jdi.request.EventRequest;
42-
import com.sun.jdi.request.EventRequestManager;
43-
import com.sun.jdi.request.MethodEntryRequest;
4440

4541
public class ConfigurationDoneRequestHandler implements IDebugRequestHandler {
4642

@@ -69,24 +65,11 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
6965
private void handleDebugEvent(DebugEvent debugEvent, IDebugSession debugSession, IDebugAdapterContext context) {
7066
Event event = debugEvent.event;
7167
boolean isImportantEvent = true;
72-
MethodEntryRequest request = null;
7368
if (event instanceof VMStartEvent) {
7469
if (context.isVmStopOnEntry()) {
75-
EventRequestManager manager = debugSession.getVM().eventRequestManager();
76-
request = manager.createMethodEntryRequest();
77-
request.addClassFilter(context.getMainClass());
78-
request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
79-
request.enable();
80-
}
81-
} else if (event instanceof MethodEntryEvent) {
82-
Method method = ((MethodEntryEvent) event).method();
83-
if (method.name().equals("main") && method.isStatic() && method.isPublic() && method.signature().equals("([Ljava/lang/String;)V")) {
84-
ThreadReference bpThread = ((MethodEntryEvent) event).thread();
85-
context.sendEvent(new Events.StoppedEvent("entry", bpThread.uniqueID()));
86-
debugEvent.shouldResume = false;
87-
if (request != null) {
88-
request.disable();
89-
}
70+
DebugUtility.stopOnEntry(debugSession, context.getMainClass()).thenAccept(threadId -> {
71+
context.sendEvent(new Events.StoppedEvent("entry", threadId));
72+
});
9073
}
9174
} else if (event instanceof VMDeathEvent) {
9275
context.setVmTerminated();

0 commit comments

Comments
 (0)