JDK-8306472 : Add virtual threads support to JDWP ThreadReference.Stop and JDI ThreadReference.stop()
  • Type: CSR
  • Component: core-svc
  • Sub-Component: debugger
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 21
  • Submitted: 2023-04-19
  • Updated: 2023-05-16
  • Resolved: 2023-04-21
Related Reports
CSR :  
Relates :  
Description
Summary
-------

JDWP ThreadReference.Stop and JDI ThreadReference.stop() is updated to support virtual threads. 

Problem
-------

JDWP ThreadReference.Stop and JDI ThreadReference.stop() may be used to send an asynchronous exception to a platform thread. They need to be extended to support virtual threads as well. This parallels the support being added to JVMTI StopThread.

Solution
--------

The  specs for JDWP ThreadReference.Stop and JDI ThreadReference.stop() are updated so that they can be used to send an asynchronous exception to a virtual thread in some situations.

For JDWP, the error code NOT_IMPLEMENTED is removed. Two new error codes are added instead: THREAD_NOT_SUSPENDED and ERROR_OPAQUE_FRAME.

For JDI, the exception UnsupportedOperationException is removed. OpaqueFrameException is added and IllegalThreadStateException is given an additional meaning.

Specification
-------------

**The JDWP spec includes the following changes below:**

The ThreadReference.Stop command description is updated to replace the following:

    The target VM may not support, or may only provide limited support, for 
    this command when the thread is a virtual thread. It may, for example, 
    only support this command when the virtual thread is suspended at a 
    breakpoint or singlestep event.

with:

    This command may be used to send an asynchronous
    exception to a virtual thread when it is suspended at an event.
    An implementation may support sending an asynchronous exception
    to a suspended virtual thread in other cases.

The following ThreadReference.Stop error code description is removed:

    NOT_IMPLEMENTED: The thread is a virtual thread and the target 
    VM does not support the command on virtual threads.

The following two ThreadReference.Stop error code descriptions are added:

    THREAD_NOT_SUSPENDED:
    The thread is a virtual thread and was not suspended.

    ERROR_OPAQUE_FRAME:
    The thread is a suspended virtual thread and the implementation 
    was unable to throw an asynchronous exception from the thread's current frame.

The general description of the OPAQUE_FRAME error code is updated to replace the following:

    OPAQUE_FRAME	32
    Information about the frame is not available (e.g. native frame) or the target VM
    is unable to perform an operation on the frame. 

with:

    OPAQUE_FRAME	32
    Information about the frame is not available (e.g. native frame) or the target VM
    is unable to perform an operation on the thread's current frame. 

**The JDI spec includes the following changes below:**

The ThreadReference.stop() method description is updated to replace the following:

    The target VM may not support, or may only provide limited support,
    for stopping a virtual thread with an asynchronous exception. It may,
    for example, only support this operation when the virtual thread is
    suspended at a breakpoint or singlestep event.

with:

    This method may be used to send an asynchronous
    exception to a virtual thread when it is suspended at an event.
    An implementation may support sending an asynchronous exception
    to a suspended virtual thread in other cases.

The following ThreadReference.stop() exception description is removed:

    * @throws UnsupportedOperationException if the thread is a virtual
    * thread and the target VM does not support this operation on
    * virtual threads

The following ThreadReference.stop() exception description was modified from:

    * @throws IllegalThreadStateException if the thread has terminated

to:

    * @throws IllegalThreadStateException if the thread has terminated,
    * or if the thread is a virtual thread and was not suspended

The following ThreadReference.stop() exception description is added:

    * @throws OpaqueFrameException if the thread is a suspended 
    * virtual thread and the implementation was unable to throw an
    * asynchronous exception from the thread's current frame

**Diff for JDWP spec**

    diff --git a/src/java.se/share/data/jdwp/jdwp.spec b/src/java.se/share/data/jdwp/jdwp.spec
    index be0bf8d39d13..f788255187c8 100644
    --- a/src/java.se/share/data/jdwp/jdwp.spec
    +++ b/src/java.se/share/data/jdwp/jdwp.spec
    @@ -2004,10 +2004,11 @@ JDWP "Java(tm) Debug Wire Protocol"
         (Command Stop=10
             "Stops the thread with an asynchronous exception. "
             "<p>"
    -        "The target VM may not support, or may only provide limited support, for "
    -        "this command when the thread is a virtual thread. It may, for example, "
    -        "only support this command when the virtual thread is suspended at a "
    -        "breakpoint or singlestep event."
    +        "This command may be used to send an asynchronous "
    +        "exception to a virtual thread when it is suspended at an event. "
    +        "An implementation may support sending an asynchronous exception "
    +        "to a suspended virtual thread in other cases."
    +
             (Out
                 (threadObject thread "The thread object ID. ")
                 (object throwable "Asynchronous exception. This object must "
    @@ -2018,8 +2019,10 @@ JDWP "Java(tm) Debug Wire Protocol"
             (ErrorSet
                 (Error INVALID_THREAD "The thread is null, not a valid thread, or the thread "
                                       "is not alive.")
    -            (Error NOT_IMPLEMENTED "The thread is a virtual thread and the target "
    -                                  "VM does not support the command on virtual threads.")
    +            (Error THREAD_NOT_SUSPENDED "The thread is a virtual thread and was not suspended.")
    +            (Error OPAQUE_FRAME   "The thread is a suspended virtual thread and the implementation "
    +                                  "was unable to throw an asynchronous exception "
    +                                  "from the thread's current frame.")
                 (Error INVALID_OBJECT "If thread is not a known ID or the asynchronous "
                                       "exception has been garbage collected.")
                 (Error VM_DEAD)
    @@ -3166,7 +3169,7 @@ JDWP "Java(tm) Debug Wire Protocol"
                                               "call stack.")
         (Constant OPAQUE_FRAME           =32  "Information about the frame is not available "
                                               "(e.g. native frame) or the target VM is unable "
    -                                          "to perform an operation on the frame.")
    +                                          "to perform an operation on the thread's current frame.")
         (Constant NOT_CURRENT_FRAME      =33  "Operation can only be performed on current frame.")
         (Constant TYPE_MISMATCH          =34  "The variable is not an appropriate type for "
                                               "the function used.")

**Diff for JDI spec:**

    diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java b/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
    index a49fe4c547ce..c66805d38f35 100644
    --- a/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
    +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
    @@ -116,18 +116,20 @@ public interface ThreadReference extends ObjectReference {
          * A debugger thread in the target VM will stop this thread
          * with the given {@link java.lang.Throwable} object.
          * <p>
    -     * The target VM may not support, or may only provide limited support,
    -     * for stopping a virtual thread with an asynchronous exception. It may,
    -     * for example, only support this operation when the virtual thread is
    -     * suspended at a breakpoint or singlestep event.
    +     * This method may be used to send an asynchronous
    +     * exception to a virtual thread when it is suspended at an event.
    +     * An implementation may support sending an asynchronous exception
    +     * to a suspended virtual thread in other cases.
    +
          *
          * @param throwable the asynchronous exception to throw
          * @throws InvalidTypeException if <code>throwable</code> is not
          * an instance of java.lang.Throwable in the target VM
    -     * @throws IllegalThreadStateException if the thread has terminated
    -     * @throws UnsupportedOperationException if the thread is a virtual
    -     * thread and the target VM does not support this operation on
    -     * virtual threads
    +     * @throws IllegalThreadStateException if the thread has terminated,
    +     * or if the thread is a virtual thread and was not suspended
    +     * @throws OpaqueFrameException if the thread is a suspended
    +     * virtual thread and the implementation was unable to throw an
    +     * asynchronous exception from the thread's current frame
          * @throws VMCannotBeModifiedException if the VirtualMachine is read-only
          * @see VirtualMachine#canBeModified()
          */

Comments
[~dholmes]There were spec updates in the PR 3 and 4 days ago, but I updated this CSR at the same time.
16-05-2023

[~cjplummer] thanks for clarifying. For some reason I saw the PR emails very recently yet they were for commits made 2 weeks ago. Sorry for the noise.
16-05-2023

[~dholmes] I updated the CSR when I made the PR changes.
15-05-2023

[~cjplummer] are any updates to this CSR request needed based on late changes to the PR? I saw mention of "minor spec updates".
15-05-2023

Moving to Approved.
21-04-2023

Looks good.
20-04-2023