diff --git a/org.eclipse.jdt.debug.tests/java23/Main21.java b/org.eclipse.jdt.debug.tests/java23/Main21.java new file mode 100644 index 0000000000..80548434b6 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/java23/Main21.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2024 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation -- initial API and implementation + *******************************************************************************/ +public class Main21 { + public static void main(String[] args) throws InterruptedException { + try { + Thread.startVirtualThread(() -> { + int p = 21; + System.out.println("From Virtual Thread"); + }).join(); + } catch (Exception e) { + + } + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java index 966db128c3..f0c51d4b21 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java @@ -633,6 +633,7 @@ synchronized void assert23Project() { jp.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_23); cfgs.add(createLaunchConfiguration(jp, "Main1")); cfgs.add(createLaunchConfiguration(jp, "Main2")); + cfgs.add(createLaunchConfiguration(jp, "Main21")); loaded23 = true; waitForBuild(); assertNoErrorMarkersExist(jp.getProject()); diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java index 9e866710b9..a1c4b892bd 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java @@ -150,6 +150,7 @@ import org.eclipse.jdt.debug.tests.ui.JavaSnippetEditorTest; import org.eclipse.jdt.debug.tests.ui.OpenFromClipboardTests; import org.eclipse.jdt.debug.tests.ui.ViewManagementTests; +import org.eclipse.jdt.debug.tests.ui.VirtualThreadsDebugViewTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests18; import org.eclipse.jdt.debug.tests.variables.DetailFormatterTests; @@ -417,5 +418,8 @@ public AutomatedSuite() { if (JavaProjectHelper.isJava16_Compatible()) { addTest(new TestSuite(RecordBreakpointTests.class)); } + if (Runtime.version().feature() == 23 && JavaProjectHelper.isJava23_Compatible()) { + addTest(new TestSuite(VirtualThreadsDebugViewTests.class)); + } } } diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/VirtualThreadsDebugViewTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/VirtualThreadsDebugViewTests.java new file mode 100644 index 0000000000..fc2f4a656d --- /dev/null +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ui/VirtualThreadsDebugViewTests.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2024 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation -- initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.debug.tests.ui; + +import org.eclipse.core.resources.IFile; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.internal.ui.views.console.ProcessConsole; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.debug.core.IJavaBreakpoint; +import org.eclipse.jdt.debug.core.IJavaThread; +import org.eclipse.jdt.debug.tests.TestUtil; +import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants; +import org.eclipse.jdt.internal.debug.core.model.JDIThread; +import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.test.OrderedTestSuite; + +import junit.framework.Test; + +/** + * Tests for debug view. + */ +public class VirtualThreadsDebugViewTests extends AbstractDebugUiTests { + + + public static Test suite() { + return new OrderedTestSuite(VirtualThreadsDebugViewTests.class); + } + + private boolean showMonitorsOriginal; + + public VirtualThreadsDebugViewTests(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore(); + showMonitorsOriginal = jdiUIPreferences.getBoolean(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO); + jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, true); + resetPerspective(DebugViewPerspectiveFactory.ID); + processUiEvents(100); + } + + @Override + protected void tearDown() throws Exception { + IPreferenceStore jdiUIPreferences = JDIDebugUIPlugin.getDefault().getPreferenceStore(); + jdiUIPreferences.setValue(IJavaDebugUIConstants.PREF_SHOW_MONITOR_THREAD_INFO, showMonitorsOriginal); + sync(() -> getActivePage().closeAllEditors(false)); + processUiEvents(100); + super.tearDown(); + } + + @Override + protected IJavaProject getProjectContext() { + return super.get23Project(); + } + + public void testVirtualThreadDebugView() throws Exception { + sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class)); + final String typeName = "Main21"; + final int bpLine = 19; + + IJavaBreakpoint bp = createLineBreakpoint(bpLine, "", typeName + ".java", typeName); + bp.setSuspendPolicy(IJavaBreakpoint.SUSPEND_THREAD); + IFile file = (IFile) bp.getMarker().getResource(); + assertEquals(typeName + ".java", file.getName()); + + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + assertNotNull("Launch unsuccessful", mainThread); + openEditorInDebug(file); + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + IDebugView debugViewer = (IDebugView) getActivePage().findView(IDebugUIConstants.ID_DEBUG_VIEW); + ISelection currentSelection = debugViewer.getViewer().getSelection(); + assertNotNull("Debug View is not available", debugViewer); + if (currentSelection instanceof IStructuredSelection) { + Object sel = ((IStructuredSelection) currentSelection).getFirstElement(); + if (sel instanceof IStackFrame stackFrame) { + IThread thread = stackFrame.getThread(); + JDIThread vThread = (JDIThread) stackFrame.getThread(); + assertTrue("Not a Virtual thread", vThread.isVirtualThread()); + StructuredSelection select = new StructuredSelection(thread); + debugViewer.getViewer().setSelection(select, true); + IDebugModelPresentation md = DebugUITools.newDebugModelPresentation(); + String groupName = md.getText(thread); + assertTrue("Not a Virtual thread grouping", groupName.contains("Virtual")); + } + } + } + }); + mainThread.resume(); + } catch (Exception e) { + DebugPlugin.log(e); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + private void openEditorInDebug(IFile file) throws Exception { + // Let now all pending jobs proceed, ignore console jobs + sync(() -> TestUtil.waitForJobs(getName(), 1000, 10000, ProcessConsole.class)); + @SuppressWarnings("unused") + CompilationUnitEditor part = (CompilationUnitEditor) sync(() -> openEditor(file)); + processUiEvents(100); + } + + @Override + protected boolean enableUIEventLoopProcessingInWaiter() { + return true; + } + +} diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java index c4392c0273..223d5fa756 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -243,6 +243,23 @@ public class DebugUIMessages extends NLS { public static String thread_daemon_system_suspended_fieldmodification; public static String thread_daemon_system_suspended_runtoline; public static String thread_daemon_system_suspended_classprepare; + + public static String thread_virtual_terminated; + public static String thread_virtual_evaluating; + public static String thread_virtual_running; + public static String thread_virtual_stepping; + public static String thread_virtual_suspended; + public static String thread_virtual_suspended_problem; + public static String thread_virtual_suspended_fieldaccess; + public static String thread_virtual_suspended_linebreakpoint; + public static String thread_virtual_suspended_methodentry; + public static String thread_virtual_suspended_exception; + public static String thread_virtual_suspended_exception_uncaught; + public static String thread_virtual_suspended_methodexit; + public static String thread_virtual_suspended_fieldmodification; + public static String thread_virtual_suspended_runtoline; + public static String thread_virtual_suspended_classprepare; + public static String SuspendTimeoutHandler_suspend; public static String SuspendTimeoutHandler_timeout_occurred; public static String JDIDebugUIPlugin_Searching_1; diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties index 19af00256f..e93b81afbd 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2022 IBM Corporation and others. +# Copyright (c) 2000, 2024 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -184,6 +184,21 @@ thread_daemon_system_suspended_fieldmodification=Daemon System Thread [{0}] (Sus thread_daemon_system_suspended_runtoline=Daemon System Thread [{0}] (Suspended (run to line {1} in {2})) thread_daemon_system_suspended_classprepare=Daemon System Thread [{0}] (Class load: {1}) +thread_virtual_terminated=Virtual Thread [{0}] (Terminated) +thread_virtual_evaluating=Virtual Thread [{0}] (Evaluating) +thread_virtual_running=Virtual Thread [{0}] (Running) +thread_virtual_stepping=Virtual Thread [{0}] (Stepping) +thread_virtual_suspended=Virtual Thread [{0}] (Suspended) +thread_virtual_suspended_problem=Virtual Thread [{0}] (Suspended ({1})) +thread_virtual_suspended_fieldaccess=Virtual Thread [{0}] (Suspended (access of field {1} in {2})) +thread_virtual_suspended_linebreakpoint=Virtual Thread [{0}] (Suspended (breakpoint at line {1} in {2})) +thread_virtual_suspended_methodentry=Virtual Thread [{0}] (Suspended (entry into method {1} in {2})) +thread_virtual_suspended_exception=Virtual Thread [{0}] (Suspended (exception {1})) +thread_virtual_suspended_exception_uncaught=Virtual Thread [{0}] (Suspended (uncaught exception {1})) +thread_virtual_suspended_methodexit=Virtual Thread [{0}] (Suspended (exit of method {1} in {2})) +thread_virtual_suspended_fieldmodification=Virtual Thread [{0}] (Suspended (modification of field {1} in {2})) +thread_virtual_suspended_runtoline=Virtual Thread [{0}] (Suspended (run to line {1} in {2})) +thread_virtual_suspended_classprepare=Virtual Thread [{0}] (Class load: {1}) ############################################################################### JDIModelPresentation_target_suspended=\ (Suspended) diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java index 560e368488..9f61178eb0 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -318,6 +318,10 @@ protected String getThreadText(IJavaThread thread, boolean qualified) throws Cor } if (thread.isSystemThread()) { key.append("system_"); //$NON-NLS-1$ + } else if (thread instanceof JDIThread jdi) { + if (jdi.isVirtualThread()) { + key.append("virtual_"); //$NON-NLS-1$ + } } if (thread.isTerminated()) { key.append("terminated"); //$NON-NLS-1$ @@ -325,7 +329,8 @@ protected String getThreadText(IJavaThread thread, boolean qualified) throws Cor } else if (thread.isStepping()) { key.append("stepping"); //$NON-NLS-1$ args = new String[] {thread.getName()}; - } else if ((thread instanceof JDIThread && ((JDIThread)thread).isSuspendVoteInProgress()) && !thread.getDebugTarget().isSuspended()) { + } else if ((thread instanceof JDIThread jdi && jdi.isSuspendVoteInProgress()) && !thread.getDebugTarget().isSuspended() + && !jdi.isVirtualThread()) { // show running when listener notification is in progress key.append("running"); //$NON-NLS-1$ args = new String[] {thread.getName()}; @@ -415,8 +420,15 @@ protected String getThreadText(IJavaThread thread, boolean qualified) throws Cor args = new String[] {thread.getName()}; } } + if (args[0].isEmpty() && thread instanceof JDIThread jdi && jdi.isVirtualThread()) { // Virtual Thread + long virtualThreadID = thread.getThreadObject().getUniqueId(); + String id = "ID#" + virtualThreadID; //$NON-NLS-1$ + args[0] = id; + } try { - return getFormattedString((String)DebugUIMessages.class.getDeclaredField(key.toString()).get(null), args); + + return getFormattedString((String) DebugUIMessages.class.getDeclaredField(key.toString()).get(null), args); + } catch (IllegalArgumentException e) { JDIDebugUIPlugin.log(e); } catch (SecurityException e) { diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/BreakpointListenerManager.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/BreakpointListenerManager.java index 6d35a779c7..74b230a239 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/BreakpointListenerManager.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/BreakpointListenerManager.java @@ -60,8 +60,7 @@ public class BreakpointListenerManager { /** * Proxy to a breakpoint listener */ - private class JavaBreakpointListenerProxy implements - IJavaBreakpointListener { + private class JavaBreakpointListenerProxy implements IJavaBreakpointListener { private final IConfigurationElement fConfigElement; private IJavaBreakpointListener fDelegate; @@ -78,8 +77,7 @@ public JavaBreakpointListenerProxy(IConfigurationElement element) { private synchronized IJavaBreakpointListener getDelegate() { if (fDelegate == null) { try { - fDelegate = (IJavaBreakpointListener) fConfigElement - .createExecutableExtension(ATTR_CLASS); + fDelegate = (IJavaBreakpointListener) fConfigElement.createExecutableExtension(ATTR_CLASS); } catch (CoreException e) { JDIDebugPlugin.log(e); } @@ -91,14 +89,11 @@ private synchronized IJavaBreakpointListener getDelegate() { /* * (non-Javadoc) * - * @see - * org.eclipse.jdt.debug.core.IJavaBreakpointListener#addingBreakpoint - * (org.eclipse.jdt.debug.core.IJavaDebugTarget, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener#addingBreakpoint (org.eclipse.jdt.debug.core.IJavaDebugTarget, * org.eclipse.jdt.debug.core.IJavaBreakpoint) */ @Override - public void addingBreakpoint(IJavaDebugTarget target, - IJavaBreakpoint breakpoint) { + public void addingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { delegate.addingBreakpoint(target, breakpoint); @@ -121,14 +116,11 @@ boolean isGlobal() { /* * (non-Javadoc) * - * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener# - * breakpointHasCompilationErrors - * (org.eclipse.jdt.debug.core.IJavaLineBreakpoint, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener# breakpointHasCompilationErrors (org.eclipse.jdt.debug.core.IJavaLineBreakpoint, * org.eclipse.jdt.core.dom.Message[]) */ @Override - public void breakpointHasCompilationErrors( - IJavaLineBreakpoint breakpoint, Message[] errors) { + public void breakpointHasCompilationErrors(IJavaLineBreakpoint breakpoint, Message[] errors) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { delegate.breakpointHasCompilationErrors(breakpoint, errors); @@ -138,14 +130,11 @@ public void breakpointHasCompilationErrors( /* * (non-Javadoc) * - * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener# - * breakpointHasRuntimeException - * (org.eclipse.jdt.debug.core.IJavaLineBreakpoint, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener# breakpointHasRuntimeException (org.eclipse.jdt.debug.core.IJavaLineBreakpoint, * org.eclipse.debug.core.DebugException) */ @Override - public void breakpointHasRuntimeException( - IJavaLineBreakpoint breakpoint, DebugException exception) { + public void breakpointHasRuntimeException(IJavaLineBreakpoint breakpoint, DebugException exception) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { delegate.breakpointHasRuntimeException(breakpoint, exception); @@ -155,9 +144,7 @@ public void breakpointHasRuntimeException( /* * (non-Javadoc) * - * @see - * org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointHit( - * org.eclipse.jdt.debug.core.IJavaThread, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointHit( org.eclipse.jdt.debug.core.IJavaThread, * org.eclipse.jdt.debug.core.IJavaBreakpoint) */ @Override @@ -172,31 +159,26 @@ public int breakpointHit(IJavaThread thread, IJavaBreakpoint breakpoint) { /* * (non-Javadoc) * - * @see - * org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointInstalled - * (org.eclipse.jdt.debug.core.IJavaDebugTarget, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointInstalled (org.eclipse.jdt.debug.core.IJavaDebugTarget, * org.eclipse.jdt.debug.core.IJavaBreakpoint) */ @Override - public void breakpointInstalled(IJavaDebugTarget target, - IJavaBreakpoint breakpoint) { + public void breakpointInstalled(IJavaDebugTarget target, IJavaBreakpoint breakpoint) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { delegate.breakpointInstalled(target, breakpoint); } + } /* * (non-Javadoc) * - * @see - * org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointRemoved - * (org.eclipse.jdt.debug.core.IJavaDebugTarget, + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener#breakpointRemoved (org.eclipse.jdt.debug.core.IJavaDebugTarget, * org.eclipse.jdt.debug.core.IJavaBreakpoint) */ @Override - public void breakpointRemoved(IJavaDebugTarget target, - IJavaBreakpoint breakpoint) { + public void breakpointRemoved(IJavaDebugTarget target, IJavaBreakpoint breakpoint) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { delegate.breakpointRemoved(target, breakpoint); @@ -206,22 +188,17 @@ public void breakpointRemoved(IJavaDebugTarget target, /* * (non-Javadoc) * - * @see - * org.eclipse.jdt.debug.core.IJavaBreakpointListener#installingBreakpoint - * (org.eclipse.jdt.debug.core.IJavaDebugTarget, - * org.eclipse.jdt.debug.core.IJavaBreakpoint, - * org.eclipse.jdt.debug.core.IJavaType) + * @see org.eclipse.jdt.debug.core.IJavaBreakpointListener#installingBreakpoint (org.eclipse.jdt.debug.core.IJavaDebugTarget, + * org.eclipse.jdt.debug.core.IJavaBreakpoint, org.eclipse.jdt.debug.core.IJavaType) */ @Override - public int installingBreakpoint(IJavaDebugTarget target, - IJavaBreakpoint breakpoint, IJavaType type) { + public int installingBreakpoint(IJavaDebugTarget target, IJavaBreakpoint breakpoint, IJavaType type) { IJavaBreakpointListener delegate = getDelegate(); if (delegate != null) { return delegate.installingBreakpoint(target, breakpoint, type); } return IJavaBreakpointListener.DONT_CARE; } - } /** @@ -231,23 +208,15 @@ private synchronized void init() { if (fgJavaBreakpointListenersMap == null) { fgJavaBreakpointListenersMap = new HashMap<>(); List global = new ArrayList<>(); - IExtensionPoint extensionPoint = Platform - .getExtensionRegistry() - .getExtensionPoint( - JDIDebugPlugin.getUniqueIdentifier(), - JDIDebugPlugin.EXTENSION_POINT_JAVA_BREAKPOINT_LISTENERS); - IConfigurationElement[] actionDelegateElements = extensionPoint - .getConfigurationElements(); + IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(JDIDebugPlugin.getUniqueIdentifier(), JDIDebugPlugin.EXTENSION_POINT_JAVA_BREAKPOINT_LISTENERS); + IConfigurationElement[] actionDelegateElements = extensionPoint.getConfigurationElements(); for (IConfigurationElement actionDelegateElement : actionDelegateElements) { try { String id = actionDelegateElement.getAttribute(ATTR_ID); - if (id == null) - throw new CoreException( - new Status(IStatus.ERROR, JDIDebugPlugin - .getUniqueIdentifier(), - "Java breakpoint listener requires an identifier attribute.")); //$NON-NLS-1$ - JavaBreakpointListenerProxy listener = new JavaBreakpointListenerProxy( - actionDelegateElement); + if (id == null) { + throw new CoreException(new Status(IStatus.ERROR, JDIDebugPlugin.getUniqueIdentifier(), "Java breakpoint listener requires an identifier attribute.")); //$NON-NLS-1$ + } + JavaBreakpointListenerProxy listener = new JavaBreakpointListenerProxy(actionDelegateElement); fgJavaBreakpointListenersMap.put(id, listener); if (listener.isGlobal()) { global.add(listener); @@ -256,14 +225,12 @@ private synchronized void init() { JDIDebugPlugin.log(e); } } - fgGlobalListeners = global - .toArray(new IJavaBreakpointListener[global.size()]); + fgGlobalListeners = global.toArray(new IJavaBreakpointListener[global.size()]); } } /** - * Returns the listener registered with the given identifier or - * null if none. + * Returns the listener registered with the given identifier or null if none. * * @param id * extension identifier @@ -275,8 +242,7 @@ public IJavaBreakpointListener getBreakpointListener(String id) { } /** - * Returns breakpoint listener extensions registered to listen for changes - * to all breakpoints. + * Returns breakpoint listener extensions registered to listen for changes to all breakpoints. * * @return global listeners */ diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java index c5cfd20ecc..c8063b6b46 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -177,6 +177,7 @@ public class JDIThread extends JDIDebugElement implements IJavaThread { * @since 3.3 */ private boolean fIsDaemon; + private boolean fIsVirtualThread; /** * Lock used to guard access to internal data that need to be updated in atomic manner @@ -362,6 +363,7 @@ protected void initialize() throws ObjectCollectedException { // system thread try { determineIfSystemThread(); + determineIfSVirtualThread(); } catch (DebugException e) { Throwable underlyingException = e.getStatus().getException(); if (underlyingException instanceof VMDisconnectedException) { @@ -560,6 +562,25 @@ protected void determineIfSystemThread() throws DebugException { } } + /** + * Determines whether this is a virtual thread. + * + * @throws DebugException + * on failure + */ + protected void determineIfSVirtualThread() throws DebugException { + try { + ReferenceType referenceType = getUnderlyingThread().referenceType(); + if (referenceType.name().equals("java.lang.VirtualThread")) { //$NON-NLS-1$ + fIsVirtualThread = true; + fIsSystemThread = false; + } + } catch (RuntimeException e) { + targetRequestFailed("Unable to determine thread daemon status", e); //$NON-NLS-1$ + } + } + + /** * Determines whether this is a daemon thread. * @@ -1582,6 +1603,10 @@ public boolean isDaemon() throws DebugException { return fIsDaemon; } + public boolean isVirtualThread() { + return fIsVirtualThread; + } + @Override public String getThreadGroupName() throws DebugException { if (fThreadGroupName == null) { @@ -1883,7 +1908,6 @@ protected boolean shouldDoStepReturn() throws DebugException { public void suspend() throws DebugException { // prepare for the suspend request prepareForClientSuspend(); - synchronized (this) { try { // Abort any pending step request