JDK-8364314 : java_lang_Thread::get_thread_status fails assert(base != nullptr) failed: Invalid base
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 26
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux,windows
  • CPU: x86_64,aarch64
  • Submitted: 2025-07-29
  • Updated: 2025-08-05
  • Resolved: 2025-08-04
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 26
26 masterFixed
Related Reports
Causes :  
Relates :  
Relates :  
Sub Tasks
JDK-8364325 :  
Description
The following test failed in the JDK26 CI:

com/sun/management/HotSpotDiagnosticMXBean/DumpThreads.java

Here's a snippet from the log file:

#section:junit
----------messages:(8/639)----------
command: junit -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI --enable-native-access=ALL-UNNAMED -Djdk.trackAllThreads=false DumpThreads
reason: User specified action: run junit/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI --enable-native-access=ALL-UNNAMED -Djdk.trackAllThreads=false DumpThreads 
started: Tue Jul 29 19:19:47 UTC 2025
Mode: othervm [/othervm specified]
Additional options from @modules: --add-modules java.base,jdk.management --add-exports java.base/jdk.internal.vm=ALL-UNNAMED
Process id: 4166196
finished: Tue Jul 29 19:20:34 UTC 2025
elapsed time (seconds): 47.063
----------configuration:(4/107)----------
Boot Layer
  add modules: java.base jdk.management  
  add exports: java.base/jdk.internal.vm ALL-UNNAMED

----------System.out:(22/1955)----------
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/opt/mach5/mesos/work_dir/slaves/f7f8bd65-a387-4a2b-b519-702f2fefaf87-S165948/frameworks/1735e8a2-a1db-478c-8104-60c8b0af87dd-0196/executors/7526ff7e-6658-4f55-ae82-dfc9c6a76be0/runs/c7e3ce10-fdf6-4c2d-95b6-5580d28aee48/workspace/open/src/hotspot/share/gc/z/zBarrierSet.inline.hpp:60), pid=4166196, tid=4166392
#  assert(base != nullptr) failed: Invalid base
#
# JRE version: Java(TM) SE Runtime Environment (26.0+9) (fastdebug build 26-ea+9-879)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 26-ea+9-879, compiled mode, sharing, compressed class ptrs, z gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x6ab674]  AccessInternal::PostRuntimeDispatch<ZBarrierSet::AccessBarrier<286790ul, ZBarrierSet>, (AccessInternal::BarrierType)3, 286790ul>::oop_access_barrier(oop, long)+0x1f4
#
# Core dump will be written. Default location: Core dumps may be processed with "/opt/core.sh %p" (or dumping to /opt/mach5/mesos/work_dir/slaves/f7f8bd65-a387-4a2b-b519-702f2fefaf87-S166055/frameworks/1735e8a2-a1db-478c-8104-60c8b0af87dd-0196/executors/f3803a0b-91f6-49f9-85e9-9f7cabef76d0/runs/584aadfc-c272-418f-bb91-ae0a5d6d46fb/testoutput/test-support/jtreg_open_test_jdk_jdk_loom/scratch/5/core.4166196)
#
# An error report file with more information is saved as:
# /opt/mach5/mesos/work_dir/slaves/f7f8bd65-a387-4a2b-b519-702f2fefaf87-S166055/frameworks/1735e8a2-a1db-478c-8104-60c8b0af87dd-0196/executors/f3803a0b-91f6-49f9-85e9-9f7cabef76d0/runs/584aadfc-c272-418f-bb91-ae0a5d6d46fb/testoutput/test-support/jtreg_open_test_jdk_jdk_loom/scratch/5/hs_err_pid4166196.log
[40.369s][warning][os] Loading hsdis library failed
     Locks owned:
    Mutex: [0x00007f56d4377808] HandshakeState_lock - owner: 0x00007f5754328640 allow_vm_block nosafepoint
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
----------System.err:(29/2368)----------
STARTED    DumpThreads::testParkedThreadWhenPinned 'testParkedThreadWhenPinned()'
org.opentest4j.TestAbortedException: Assumption failed: This test requires all threads to be tracked
ABORTED    DumpThreads::testParkedThreadWhenPinned 'testParkedThreadWhenPinned()' [740ms]
STARTED    DumpThreads::testPlainText 'testPlainText()'
Dumped to dump13792432401610819191.txt
SUCCESSFUL DumpThreads::testPlainText 'testPlainText()' [3367ms]
STARTED    DumpThreads::testWaitingThreadWhenPinned 'testWaitingThreadWhenPinned()'
org.opentest4j.TestAbortedException: Assumption failed: This test requires all threads to be tracked
ABORTED    DumpThreads::testWaitingThreadWhenPinned 'testWaitingThreadWhenPinned()' [59ms]
STARTED    DumpThreads::testThreadOwnsMonitor '[1] java.lang.ThreadBuilders$PlatformThreadFactory@253aa579'
Dumped to dump9071906702727467063.txt
Dumped to dump11440884598178860391.json
SUCCESSFUL DumpThreads::testThreadOwnsMonitor '[1] java.lang.ThreadBuilders$PlatformThreadFactory@253aa579' [1571ms]
STARTED    DumpThreads::testThreadOwnsMonitorWhenPinned 'testThreadOwnsMonitorWhenPinned()'
org.opentest4j.TestAbortedException: Assumption failed: This test requires all threads to be tracked
ABORTED    DumpThreads::testThreadOwnsMonitorWhenPinned 'testThreadOwnsMonitorWhenPinned()' [2ms]
STARTED    DumpThreads::testNull 'testNull()'
SUCCESSFUL DumpThreads::testNull 'testNull()' [45ms]
STARTED    DumpThreads::testFileWriteFails 'testFileWriteFails()'
SUCCESSFUL DumpThreads::testFileWriteFails 'testFileWriteFails()' [37ms]
STARTED    DumpThreads::testJsonFormat 'testJsonFormat()'
Dumped to dump14812566658463330787.json
SUCCESSFUL DumpThreads::testJsonFormat 'testJsonFormat()' [60ms]
STARTED    DumpThreads::testFileAlreadyExists 'testFileAlreadyExists()'
SUCCESSFUL DumpThreads::testFileAlreadyExists 'testFileAlreadyExists()' [58ms]
STARTED    DumpThreads::testThreadContainer '[1] java.util.concurrent.ThreadPoolExecutor@7b25d4cd[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]'
Dumped to dump3199648731047715271.json
SUCCESSFUL DumpThreads::testThreadContainer '[1] java.util.concurrent.ThreadPoolExecutor@7b25d4cd[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]' [346ms]
STARTED    DumpThreads::testThreadContainer '[2] java.util.concurrent.ThreadPerTaskExecutor@3beef3d5'
----------rerun:(51/8130)*----------

Here's the top part of the crashing thread's stack:

---------------  T H R E A D  ---------------

Current thread (0x00007f5754328640):  JavaThread "MainThread"        [_thread_in_vm, id=4166392, stack(0x00007f5758a08000,0x00007f5758b08000) (1024K)] _threads_hazard_ptr=0x00007f56d4382f60, _nested_threads_hazard_ptr_cnt=0

Stack: [0x00007f5758a08000,0x00007f5758b08000],  sp=0x00007f5758b01de0,  free space=999k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x6ab674]  AccessInternal::PostRuntimeDispatch<ZBarrierSet::AccessBarrier<286790ul, ZBarrierSet>, (AccessInternal::BarrierType)3, 286790ul>::oop_access_barrier(oop, long)+0x1f4  (zBarrierSet.inline.hpp:60)
V  [libjvm.so+0x6ae54d]  oopDesc::obj_field(int) const+0x12d  (accessBackend.hpp:448)
V  [libjvm.so+0x10a0f1c]  java_lang_Thread::get_thread_status(oop)+0x8c  (javaClasses.cpp:1764)
V  [libjvm.so+0x1b445f1]  GetThreadSnapshotHandshakeClosure::do_thread(Thread*)+0x911  (threadService.cpp:1281)
V  [libjvm.so+0xf955f7]  HandshakeOperation::do_handshake(JavaThread*)+0x47  (handshake.cpp:331)
V  [libjvm.so+0xf95bd7]  HandshakeState::try_process(HandshakeOperation*) [clone .part.0]+0xc7  (handshake.cpp:686)
V  [libjvm.so+0xf962e7]  Handshake::execute(HandshakeClosure*, ThreadsListHandle*, JavaThread*)+0x467  (handshake.cpp:397)
V  [libjvm.so+0x1b408ee]  ThreadSnapshotFactory::get_thread_snapshot(_jobject*, JavaThread*)+0x4de  (threadService.cpp:1492)
V  [libjvm.so+0x12385b7]  JVM_CreateThreadSnapshot+0x97  (jvm.cpp:2966)
J 8808  jdk.internal.vm.ThreadSnapshot.create(Ljava/lang/Thread;)Ljdk/internal/vm/ThreadSnapshot; java.base@26-ea (0 bytes) @ 0x00007f57491087a7 [0x00007f5749108700+0x00000000000000a7]
J 8853 c2 jdk.internal.vm.ThreadSnapshot.of(Ljava/lang/Thread;)Ljdk/internal/vm/ThreadSnapshot; java.base@26-ea (92 bytes) @ 0x00007f5749118620 [0x00007f5749118600+0x0000000000000020]
J 9919 c2 jdk.internal.vm.ThreadDumper.dumpThread(Ljava/lang/Thread;Ljdk/internal/vm/ThreadDumper$JsonWriter;)Z java.base@26-ea (410 bytes) @ 0x00007f574923f340 [0x00007f574923f300+0x0000000000000040]
J 9924 c2 jdk.internal.vm.ThreadDumper.dumpThreads(Ljdk/internal/vm/ThreadContainer;Ljdk/internal/vm/ThreadDumper$JsonWriter;)V java.base@26-ea (158 bytes) @ 0x00007f574924c870 [0x00007f574924c600+0x0000000000000270]
J 9922 c2 jdk.internal.vm.ThreadDumper.lambda$dumpThreads$2(Ljdk/internal/vm/ThreadDumper$JsonWriter;Ljdk/internal/vm/ThreadContainer;)V java.base@26-ea (6 bytes) @ 0x00007f574924b4a8 [0x00007f574924b480+0x0000000000000028]

This assertion failure happened in a JVM_CreateThreadSnapshot call
which involved handshaking code and a java_lang_Thread::get_thread_status
call which appears to have run into a bad oop. I'm starting this issue off
in hotspot/runtime for initial triage.
Comments
Changeset: 84a4a364 Branch: master Author: David Holmes <dholmes@openjdk.org> Date: 2025-08-04 21:48:38 +0000 URL: https://git.openjdk.org/jdk/commit/84a4a3647c86baecc07abfa7d1d4b88e06984821
04-08-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/26544 Date: 2025-07-30 05:14:29 +0000
30-07-2025

Failure reproduces with -XX:+UseZGC -Xcomp quite reliably: 3/4.
30-07-2025

Okay I see what the problem could be. After the changes in JDK-8361912 we could "return " the carrier thread from cv_internal_thread_to_JavaThread, but before we hit the transition disabler the virtual thread could unmount. As a result when we execute this code: if (is_virtual) { // 1st need to disable mount/unmount transitions transition_disabler.init(jthread); carrier_thread = Handle(THREAD, java_lang_VirtualThread::carrier_thread(thread_h())); if (carrier_thread != nullptr) { java_thread = java_lang_Thread::thread(carrier_thread()); } } we hit the implicit else where "carrier_thread == nullptr" and we do nothing, but `java_thread` still holds the old carrier, which we then perform the handshake operation with: void do_thread(Thread* th) override { Thread* current = Thread::current(); bool is_virtual = java_lang_VirtualThread::is_instance(_thread_h()); if (_java_thread != nullptr) { if (is_virtual) { // mounted vthread, use carrier thread state oop carrier_thread = java_lang_VirtualThread::carrier_thread(_thread_h()); _thread_status = java_lang_Thread::get_thread_status(carrier_thread); } else { But this _java_thread no longer has a carrier, so `get_thread_status` is passed null and we crash.
30-07-2025

Since this is a regression, I'm bumping from P4 -> P2 since that's where we start out for regressions.
30-07-2025