On Tue, 4 Nov 2025 21:28:14 GMT, Patricio Chilano Mateo <[email protected]> wrote:
>> If a thread tries to initialize a class that is already being initialized by >> another thread, it will block until notified. Since at this blocking point >> there are native frames on the stack, a virtual thread cannot be unmounted >> and is pinned to its carrier. Besides harming scalability, this can, in some >> pathological cases, lead to a deadlock, for example, if the thread executing >> the class initialization method is blocked waiting for some unmounted >> virtual thread to run, but all carriers are blocked waiting for that class >> to be initialized. >> >> As of JDK-8338383, virtual threads blocked in the VM on `ObjectMonitor` >> operations can be unmounted. Since synchronization on class initialization >> is implemented using `ObjectLocker`, we can reuse the same mechanism to >> unmount virtual threads on these cases too. >> >> This patch adds support for unmounting virtual threads on some of the most >> common class initialization paths, specifically when calling >> `InterpreterRuntime::_new` (`new` bytecode), and >> `InterpreterRuntime::resolve_from_cache` for `invokestatic`, `getstatic` or >> `putstatic` bytecodes. In the future we might consider extending this >> mechanism to include initialization calls originating from native methods >> such as `Class.forName0`. >> >> ### Summary of implementation >> >> The ObjectLocker class was modified to not pin the continuation if we are >> coming from a preemptable path, which will be the case when calling >> `InstanceKlass::initialize_impl` from new method >> `InstanceKlass::initialize_preemptable`. This means that for these cases, a >> virtual thread can now be unmounted either when contending for the init_lock >> in the `ObjectLocker` constructor, or in the call to `wait_uninterruptibly`. >> Also, since the call to initialize a class includes a previous call to >> `link_class` which also uses `ObjectLocker` to protect concurrent calls from >> multiple threads, we will allow preemption there too. >> >> If preempted, we will throw a pre-allocated exception which will get >> propagated with the `TRAPS/CHECK` macros all the way back to the VM entry >> point. The exception will be cleared and on return back to Java the virtual >> thread will go through the preempt stub and unmount. When running again, at >> the end of the thaw call we will identify this preemption case and redo the >> original VM call (either `InterpreterRuntime::_new` or >> `InterpreterRuntime::resolve_from_cache`). >> >> ### Notes >> >> `InterpreterRuntime::call_VM_preemptable` used previously only for >> `InterpreterRuntime::mon... > > Patricio Chilano Mateo has updated the pull request with a new target base > due to a merge or a rebase. The pull request now contains 22 commits: > > - Add check for SingleStep events > - Merge branch 'master' into JDK-8369238 > - fix to JvmtiHideSingleStepping > - Suggested fix in macroAssembler_ppc.cpp > - Improve comment and assert msg > - More fixes from David's comments > - Merge branch 'master' into JDK-8369238 > - add const to references > - Improve comment in anchor_mark_set_pd > - More comments from Coleen > - ... and 12 more: https://git.openjdk.org/jdk/compare/2f455ed1...06f85198 Thanks everyone for the reviews! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27802#issuecomment-3488372018
