Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.
/ jdk22 Public archive

Commit 3984a00

Browse files
author
Alex Menkov
committed
8322237: Heap dump contains duplicate thread records for mounted virtual threads
Reviewed-by: sspitsyn Backport-of: dd8ae616437398f957f9b4f09cf2c7f1d0bd0938
1 parent 4ea14b2 commit 3984a00

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

src/hotspot/share/services/heapDumper.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,19 @@ class ThreadDumper : public CHeapObj<mtInternal> {
16411641
&& java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::TERMINATED;
16421642
}
16431643

1644+
static bool is_vthread_mounted(oop vt) {
1645+
// The code should be consistent with the "mounted virtual thread" case
1646+
// (VM_HeapDumper::dump_stack_traces(), ThreadDumper::get_top_frame()).
1647+
// I.e. virtual thread is mounted if its carrierThread is not null
1648+
// and is_vthread_mounted() for the carrier thread returns true.
1649+
oop carrier_thread = java_lang_VirtualThread::carrier_thread(vt);
1650+
if (carrier_thread == nullptr) {
1651+
return false;
1652+
}
1653+
JavaThread* java_thread = java_lang_Thread::thread(carrier_thread);
1654+
return java_thread->is_vthread_mounted();
1655+
}
1656+
16441657
ThreadDumper(ThreadType thread_type, JavaThread* java_thread, oop thread_oop);
16451658

16461659
// affects frame_count
@@ -1918,7 +1931,10 @@ void HeapObjectDumper::do_object(oop o) {
19181931
if (o->is_instance()) {
19191932
// create a HPROF_GC_INSTANCE record for each object
19201933
DumperSupport::dump_instance(writer(), o, &_class_cache);
1921-
if (java_lang_VirtualThread::is_instance(o) && ThreadDumper::should_dump_vthread(o)) {
1934+
// If we encounter an unmounted virtual thread it needs to be dumped explicitly
1935+
// (mounted virtual threads are dumped with their carriers).
1936+
if (java_lang_VirtualThread::is_instance(o)
1937+
&& ThreadDumper::should_dump_vthread(o) && !ThreadDumper::is_vthread_mounted(o)) {
19221938
_vthread_dumper->dump_vthread(o, writer());
19231939
}
19241940
} else if (o->is_objArray()) {

test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import java.util.ArrayList;
2727
import java.util.Arrays;
2828
import java.util.Collections;
29+
import java.util.HashSet;
2930
import java.util.List;
31+
import java.util.Set;
3032
import java.util.concurrent.CountDownLatch;
3133
import java.util.concurrent.TimeUnit;
3234

@@ -223,11 +225,22 @@ private static void verifyDump(File dumpFile) throws Exception {
223225
// Log all threads with stack traces and stack references.
224226
List<ThreadObject> threads = snapshot.getThreads();
225227
List<Root> roots = Collections.list(snapshot.getRoots());
228+
// And detect thread object duplicates.
229+
Set<Long> uniqueThreads = new HashSet<>();
230+
226231
log("Threads:");
227232
for (ThreadObject thread: threads) {
233+
JavaHeapObject threadObj = snapshot.findThing(thread.getId());
234+
JavaClass threadClass = threadObj.getClazz();
228235
StackTrace st = thread.getStackTrace();
229236
StackFrame[] frames = st.getFrames();
230-
log("thread " + thread.getIdString() + ", " + frames.length + " frames");
237+
log("thread " + thread.getIdString() + " (" + threadClass.getName() + "), " + frames.length + " frames");
238+
239+
if (uniqueThreads.contains(thread.getId())) {
240+
log(" - ERROR: duplicate");
241+
} else {
242+
uniqueThreads.add(thread.getId());
243+
}
231244

232245
List<Root> stackRoots = findStackRoot(roots, thread);
233246
for (int i = 0; i < frames.length; i++) {
@@ -250,6 +263,10 @@ private static void verifyDump(File dumpFile) throws Exception {
250263
}
251264
}
252265

266+
if (threads.size() != uniqueThreads.size()) {
267+
throw new RuntimeException("Thread duplicates detected (" + (threads.size() - uniqueThreads.size()) + ")");
268+
}
269+
253270
// Verify objects from thread stacks are dumped.
254271
test(snapshot, VThreadInHeapDumpTarg.VThreadMountedReferenced.class);
255272
test(snapshot, VThreadInHeapDumpTarg.PThreadReferenced.class);

0 commit comments

Comments
 (0)