This code can be used to test the class load and unload mechanism of the JDK.
It is particularly useful in reproducing a specific bug that concerns the Shenandoah GC and JFR:
Run it via java -XX:+UseShenandoahGC -XX:StartFlightRecording=filename=100us.jfr ClassUnloadTest.java > /dev/null
to get
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/home/i560383/code/jdk/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp:138), pid=3490611, tid=3490641
# Error: Shenandoah assert_forwarded failed; Object should be forwarded
Referenced from:
interior location: 0x00000007ff8b755c
inside Java heap
not in collection set
region: | 3835|R |Y|BTE 7ff800000, 7fffdbd90, 800000000|TAMS 7ff800000|UWM 7fffdbd90|U 8047K|T 0B|G 7778K|S 269K|L 0B|CP 0
Object:
0x000000078a0006d0 - klass 0x0000741e7e1c23c0 java.lang.Module
not allocated after mark start
not after update watermark
not marked strong
not marked weak
in collection set
mark: mark(is_unlocked no_hash age=0)
region: | 3600|CS |Y|BTE 78a000000, 78a800000, 78a800000|TAMS 78a800000|UWM 78a800000|U 8192K|T 8192K|G 0B|S 0B|L 7448B|CP 0
Forwardee:
(the object itself)
#
# JRE version: OpenJDK Runtime Environment (25.0) (fastdebug build 25-internal-adhoc.i560383.jdk)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 25-internal-adhoc.i560383.jdk, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, shenandoah gc, linux-amd64)
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/i560383/code/jdk/core.3490611)
#
# JFR recording file will be written. Location: /home/i560383/code/jdk/hs_err_pid3490611.jfr
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
...
V [libjvm.so+0x1c2b838] VMError::report(outputStream*, bool)+0x2e08 (shenandoahHeap.inline.hpp:138)
V [libjvm.so+0x1c2ed70] VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void const*, void const*, char const*, int, unsigned long)+0x4f0 (vmError.cpp:1795)
V [libjvm.so+0xb8bd44] report_vm_error(char const*, int, char const*, char const*, ...)+0x104 (debug.cpp:196)
V [libjvm.so+0xb8bd7d] (debug.cpp:149)
V [libjvm.so+0x180b4af] ShenandoahAsserts::print_failure(ShenandoahAsserts::SafeLevel, oop, void*, oop, char const*, char const*, char const*, int)+0x22f (shenandoahAsserts.cpp:168)
V [libjvm.so+0x180d7a5] ShenandoahAsserts::assert_forwarded(void*, oop, char const*, int)+0x295 (shenandoahAsserts.cpp:332)
V [libjvm.so+0x18a512c] void ShenandoahHeap::conc_update_with_forwarded<narrowOop>(narrowOop*)+0xac (shenandoahHeap.inline.hpp:138)
V [libjvm.so+0x18b2521] void OopOopIterateDispatch<ShenandoahConcUpdateRefsClosure>::Table::oop_oop_iterate<InstanceMirrorKlass, narrowOop>(ShenandoahConcUpdateRefsClosure*, oop, Klass*)+0x121 (shenandoahClosures.inline.hpp:246)
V [libjvm.so+0x18a8c65] void ShenandoahHeap::marked_object_iterate<ShenandoahObjectToOopClosure<ShenandoahConcUpdateRefsClosure> >(ShenandoahHeapRegion*, ShenandoahObjectToOopClosure<ShenandoahConcUpdateRefsClosure>*, HeapWordImpl**)+0xa45 (iterator.inline.hpp:300)
V [libjvm.so+0x18d901c] ShenandoahUpdateHeapRefsTask<true>::work(unsigned int)+0x30c (shenandoahHeap.inline.hpp:630)
V [libjvm.so+0x1c98dc0] WorkerThread::run()+0x80 (workerThread.cpp:69)
V [libjvm.so+0x1b4a7fa] Thread::call_run()+0xba (thread.cpp:231)
V [libjvm.so+0x1646bf8] thread_native_entry(Thread*)+0x138 (os_linux.cpp:877)
C [libc.so.6+0xa1e2e]
with fastdebug builds. On normal release builds, you probably get something like:
[1] 3630354 IOT instruction (core dumped) java -XX:+UseShenandoahGC -XX:StartFlightRecording=filename=100us.jf
This works for the current JDK head, JDK 23 and JDK 21. So I would assume that it affects all JDKs that include the Shenandoah GC at the moment of writing.
MIT