From c585f18aa717c466a6d9b157968dcb0d1fe1b668 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Sat, 25 Jul 2026 13:15:26 +0000 Subject: [PATCH 1/5] 8388449: GenShen: Degenerated cycle could be skipped 8388809: Shenandoah: Control thread may observe incorrect cancellation reason Reviewed-by: xpeng, kdnilsen Backport-of: cd7645cf921194270aecf33ee1fab1de504d95b3 --- .../gc/shenandoah/shenandoahControlThread.cpp | 27 ++++++++++--------- .../shenandoahGenerationalControlThread.cpp | 17 ++++++------ .../share/gc/shenandoah/shenandoahHeap.cpp | 14 ++++++++-- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index f2447db8210..7cf65811730 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -306,22 +306,25 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau } bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) { + // Only read the cancellation cause once. Other threads may change it. ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (heap->cancelled_gc()) { - if (heap->cancelled_cause() == GCCause::_shenandoah_stop_vm) { - return true; - } + const GCCause::Cause cancelled_cause = heap->cancelled_cause(); + if (cancelled_cause == GCCause::_no_gc) { + return false; + } - if (ShenandoahCollectorPolicy::is_allocation_failure(heap->cancelled_cause())) { - assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle, - "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); - _degen_point = point; - return true; - } + if (cancelled_cause == GCCause::_shenandoah_stop_vm) { + return true; + } - fatal("Unexpected reason for cancellation: %s", GCCause::to_string(heap->cancelled_cause())); + if (ShenandoahCollectorPolicy::is_allocation_failure(cancelled_cause)) { + assert (_degen_point == ShenandoahGC::_degenerated_outside_cycle, + "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); + _degen_point = point; + return true; } - return false; + + fatal("Unexpected reason for cancellation: %s", GCCause::to_string(cancelled_cause)); } void ShenandoahControlThread::stop_service() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 94f3409ac41..8ab7ded712c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -586,30 +586,31 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGen } bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point) { - if (!_heap->cancelled_gc()) { + // Only read the cancellation cause once. Other threads may change it. + const GCCause::Cause cancelled_cause = _heap->cancelled_cause(); + if (cancelled_cause == GCCause::_no_gc) { return false; } - if (_heap->cancelled_cause() == GCCause::_shenandoah_stop_vm - || _heap->cancelled_cause() == GCCause::_shenandoah_concurrent_gc) { - log_debug(gc, thread)("Cancellation detected, reason: %s", GCCause::to_string(_heap->cancelled_cause())); + if (cancelled_cause == GCCause::_shenandoah_stop_vm + || cancelled_cause == GCCause::_shenandoah_concurrent_gc) { + log_debug(gc, thread)("Cancellation detected, reason: %s", GCCause::to_string(cancelled_cause)); return true; } - if (ShenandoahCollectorPolicy::is_allocation_failure(_heap->cancelled_cause())) { + if (ShenandoahCollectorPolicy::is_allocation_failure(cancelled_cause)) { assert(_degen_point == ShenandoahGC::_degenerated_unset, "Should not be set yet: %s", ShenandoahGC::degen_point_to_string(_degen_point)); MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); - _requested_gc_cause = _heap->cancelled_cause(); + _requested_gc_cause = cancelled_cause; _degen_point = point; log_debug(gc, thread)("Cancellation detected:, reason: %s, degen point: %s", - GCCause::to_string(_heap->cancelled_cause()), + GCCause::to_string(cancelled_cause), ShenandoahGC::degen_point_to_string(_degen_point)); return true; } fatal("Cancel GC either for alloc failure GC, or gracefully exiting, or to pause old generation marking"); - return false; } void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause cause) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index c0df4bbe10c..aef9ed698d2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -2257,8 +2257,18 @@ size_t ShenandoahHeap::tlab_used() const { } bool ShenandoahHeap::try_cancel_gc(GCCause::Cause cause) { - const GCCause::Cause prev = _cancelled_gc.xchg(cause); - return prev == GCCause::_no_gc || prev == GCCause::_shenandoah_concurrent_gc; + while (true) { + const GCCause::Cause prev = _cancelled_gc.get(); + if (prev != GCCause::_no_gc && prev != GCCause::_shenandoah_concurrent_gc && cause != GCCause::_shenandoah_stop_vm) { + // Only when the gc has not been cancelled, or it has been cancelled to interrupt an old marking cycle + // do we allow the new cancellation request to happen. We make an exception for stopping the VM. + return false; + } + + if (_cancelled_gc.cmpxchg(cause, prev) == prev) { + return true; + } + } } void ShenandoahHeap::cancel_concurrent_mark() { From 1c4ab234948f0a92f68ccb1ddb1c25fdd3397a95 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 27 Jul 2026 06:33:12 +0000 Subject: [PATCH 2/5] 8387722: The race during initialization or lazy constants in and Map/Set Reviewed-by: jpai, alanb Backport-of: 3412d4c0dd5250f14cc6fe594355bdf2ff976417 --- src/java.base/share/classes/java/util/LazyCollections.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/java.base/share/classes/java/util/LazyCollections.java b/src/java.base/share/classes/java/util/LazyCollections.java index e15721db2ce..f74fbad358b 100644 --- a/src/java.base/share/classes/java/util/LazyCollections.java +++ b/src/java.base/share/classes/java/util/LazyCollections.java @@ -675,6 +675,12 @@ private static T orElseComputeSlowPath(final T[] array, final long offset = offsetFor(index); final Object mutex = mutexes.acquireMutex(offset); if (mutex == null) { + // There might be a race where the value is already computed and + // the mutex is cleared, so we need to re-check the value again + final T t = (T) UNSAFE.getReferenceAcquire(array, offset); + if (t != null) { + return t; + } throwIfPreviousException(index, throwables, input); // There must be an exception throw cannotReachHere(functionHolder, input); From 4b0adaadb6622be7115c74d68cf79543f03f0555 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 28 Jul 2026 15:21:17 +0000 Subject: [PATCH 3/5] 8379830: The warnings for value-based classes need updating to include use of the Reference API Reviewed-by: dholmes, darcy --- .../share/classes/java/lang/doc-files/ValueBased.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html index 3b860ce0534..0bdcf70df3a 100644 --- a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html +++ b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html @@ -1,6 +1,6 @@