JDK-8325187 : JVMTI GetThreadState says virtual thread is JVMTI_THREAD_STATE_INTERRUPTED when it no longer is
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 21,22,23
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-02-02
  • Updated: 2024-03-27
  • Resolved: 2024-03-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 23
23 b15Fixed
Related Reports
Blocks :  
Description
I ran into a test case where a virtual thread called RawMonitorWait, and a 2nd thread called Thread.interrupt() on the virtual thread. This correctly resulted in the RawMonitorWait returning JVMTI_ERROR_INTERRUPT. However, a subsequent call to GetThreadState returns with the JVMTI_THREAD_STATE_INTERRUPTED bit set. Even so, the JVM does in fact properly consider the thread not to be interrupted. A 2nd call to RawMonitorWait does properly wait rather than immediately return with JVMTI_ERROR_INTERRUPT. This issue does not exist with platform threads.

The issue seems to be that at the java level the virtual thread is still considered to be interrupted even though it is not, and that is what GetThreadState is querying when deciding if the JVMTI_THREAD_STATE_INTERRUPTED bit should be set. See JvmtiEnvBase::get_vthread_state(), which is what GetThreadState uses for virtual threads:

  jint interrupted = java_lang_Thread::interrupted(thread_oop);
    if (interrupted) {
      state |= JVMTI_THREAD_STATE_INTERRUPTED;
    }

So the issue seems to be that when the JVM calls jt->is_interrupted(true) to fetch and clear the interrupt state of the virtual thread, this information is not propagated to the java.lang.Thread instance.

And one more thing to add is that at the java level calling Thread.isInterrupted() does return true for the virtual thread even though it should not.
Comments
Changeset: 6eea5d67 Author: Serguei Spitsyn <sspitsyn@openjdk.org> Date: 2024-03-19 08:27:55 +0000 URL: https://git.openjdk.org/jdk/commit/6eea5d675566adca3fca88639008c6c0221450a4
19-03-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/18093 Date: 2024-03-01 23:26:48 +0000
01-03-2024

I've attached a test case. The output shows the issue (it is not a pass/fail test). For virtual threads you will see: RawMonitorWait => 52 Thread State => 0x200005 and for platform threads: RawMonitorWait => 52 Thread State => 0x5 Run with -v for virtual threads and no args for platform threads.
02-02-2024