RFR: 8373367: interp-only mechanism fails to work for carrier threads in a corner case [v6]
Serguei Spitsyn
sspitsyn at openjdk.org
Wed Feb 18 12:26:20 UTC 2026
On Wed, 18 Feb 2026 11:50:47 GMT, Serguei Spitsyn <sspitsyn at openjdk.org> wrote:
>> The `interp-only` mechanism is based on the `JavaThread` objects. Carrier and virtual threads can temporary share the same `JavaThread`. The `java_thread->jvmti_thread_state()` is re-linked to a virtual thread at `mount` and to the carrier thread at `unmount`. The `JvmtiThreadState` has a back link to the `JavaThread` which is also set for virtual thread at a `mount` and carrier thread at an `unmount`. Just one of these two links at the same time is set to the `JavaThread`, the other one has to be set to `nullptr`. The `interp-only` mechanism needs this invariant.
>> However, there is a corner case when this invariant is broken. It happens when the `JvmtiThreadState` for carrier thread has just been created. In such case, the link to `JavaThread` is always `non-nullptr` even though a virtual thread is currently mounted on a carrier thread. This simple update fixes the issue in the `JvmtiThreadState` ctor.
>>
>> Testing:
>> - TBD: Mach5 tiers 1-6
>
> Serguei Spitsyn has updated the pull request incrementally with one additional commit since the last revision:
>
> review: simplify interp-only; remove _thread_saved; add more asserts
I've pushed an update with the `interp_only` simplifications and dependent changes and added more assert in the most important places. So this PR is ready for re-review now. Will need to update the PR description and bug description accordingly. The main simplification is removal of the field `JvmtiThreadState:_thread_saved`.
The change includes:
- the field `JvmtiThreadState::_thread_saved` field has been removed
- the function `JvmtiThreadState::get_thread_or_saved()` has also been removed
- now the function `JvmtiThreadState:get_thread()` is semantically equal to the former `get_thread_or_saved()`
- now the function `JvmtiThreadState::set_thread()` is used for virtual threads only
- the function `JvmtiThreadState::is_interp_only_mode()` has been simplified to always return `_saved_interp_only_mode` which means interp_only_mode for specific `JvmtiThreadState`
- the function `JvmtiEnvBase::is_thread_carrying_vthread()` is used to identify the cases when the carrier thread is not active (a virtual thread has been mounted and executed at the top). Before the fix, the function `get_thread()` was returning `nullptr` in such cases.
- the comment at start of `JvmtiThreadState` constructor has been updated with the simplifications
- added more assert in the most important places
- one incorrect assert (overly strong) has been removed
Testing:
- mach5 tiers 1-6 were good but submitted again after cleanup
-------------
PR Comment: https://git.openjdk.org/jdk/pull/29436#issuecomment-3920539655
More information about the serviceability-dev
mailing list