From b4293e4ede1c4b6cdd0ec915f0b8bf3fe5c4b4ac Mon Sep 17 00:00:00 2001 From: Man Cao Date: Wed, 19 Feb 2025 16:20:50 -0800 Subject: [PATCH 1/7] G1: Use SoftMaxHeapSize to guide GC heuristics --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 5 +++++ src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 3 +++ .../share/gc/g1/g1HeapSizingPolicy.cpp | 22 +++++++++---------- src/hotspot/share/gc/g1/g1IHOPControl.cpp | 10 +++++++-- src/hotspot/share/gc/g1/g1IHOPControl.hpp | 7 ++++-- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 4c0436ad1e224..5115108a8b9c2 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2061,6 +2061,11 @@ size_t G1CollectedHeap::max_capacity() const { return max_regions() * G1HeapRegion::GrainBytes; } +size_t G1CollectedHeap::soft_max_capacity() const { + return clamp(align_up(SoftMaxHeapSize, HeapAlignment), MinHeapSize, + max_capacity()); +} + void G1CollectedHeap::prepare_for_verify() { _verifier->prepare_for_verify(); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index d1e81205cefb7..990074d3687ca 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1200,6 +1200,9 @@ class G1CollectedHeap : public CollectedHeap { // Print the maximum heap capacity. size_t max_capacity() const override; + // Print the soft maximum heap capacity. + size_t soft_max_capacity() const; + Tickspan time_since_last_collection() const { return Ticks::now() - _collection_pause_end; } // Convenience function to be used in situations where the heap type can be diff --git a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp index c35ce7c356d28..a793ad406d65e 100644 --- a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp +++ b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp @@ -55,8 +55,8 @@ double G1HeapSizingPolicy::scale_with_heap(double pause_time_threshold) { // If the heap is at less than half its maximum size, scale the threshold down, // to a limit of 1%. Thus the smaller the heap is, the more likely it is to expand, // though the scaling code will likely keep the increase small. - if (_g1h->capacity() <= _g1h->max_capacity() / 2) { - threshold *= (double)_g1h->capacity() / (double)(_g1h->max_capacity() / 2); + if (_g1h->capacity() <= _g1h->soft_max_capacity() / 2) { + threshold *= (double)_g1h->capacity() / (double)(_g1h->soft_max_capacity() / 2); threshold = MAX2(threshold, 0.01); } @@ -91,8 +91,9 @@ size_t G1HeapSizingPolicy::young_collection_expansion_amount() { double threshold = scale_with_heap(pause_time_threshold); size_t expand_bytes = 0; + size_t soft_max_capacity = _g1h->soft_max_capacity(); - if (_g1h->capacity() == _g1h->max_capacity()) { + if (_g1h->capacity() >= soft_max_capacity) { log_expansion(short_term_pause_time_ratio, long_term_pause_time_ratio, threshold, pause_time_threshold, true, 0); clear_ratio_check_data(); @@ -123,9 +124,8 @@ size_t G1HeapSizingPolicy::young_collection_expansion_amount() { if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) || (filled_history_buffer && (long_term_pause_time_ratio > threshold))) { size_t min_expand_bytes = G1HeapRegion::GrainBytes; - size_t reserved_bytes = _g1h->max_capacity(); size_t committed_bytes = _g1h->capacity(); - size_t uncommitted_bytes = reserved_bytes - committed_bytes; + size_t uncommitted_bytes = soft_max_capacity - committed_bytes; size_t expand_bytes_via_pct = uncommitted_bytes * G1ExpandByPercentOfAvailable / 100; double scale_factor = 1.0; @@ -243,14 +243,14 @@ size_t G1HeapSizingPolicy::full_collection_resize_amount(bool& expand) { "maximum_desired_capacity = %zu", minimum_desired_capacity, maximum_desired_capacity); - // Should not be greater than the heap max size. No need to adjust + size_t soft_max_capacity = _g1h->soft_max_capacity(); + // Should not be greater than the soft max capacity. No need to adjust // it with respect to the heap min size as it's a lower bound (i.e., // we'll try to make the capacity larger than it, not smaller). - minimum_desired_capacity = MIN2(minimum_desired_capacity, MaxHeapSize); - // Should not be less than the heap min size. No need to adjust it - // with respect to the heap max size as it's an upper bound (i.e., - // we'll try to make the capacity smaller than it, not greater). - maximum_desired_capacity = MAX2(maximum_desired_capacity, MinHeapSize); + minimum_desired_capacity = MIN2(minimum_desired_capacity, soft_max_capacity); + // Should not be less than the heap min size, and should not exceed + // the soft max capacity. + maximum_desired_capacity = clamp(maximum_desired_capacity, MinHeapSize, soft_max_capacity); // Don't expand unless it's significant; prefer expansion to shrinking. if (capacity_after_gc < minimum_desired_capacity) { diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.cpp b/src/hotspot/share/gc/g1/g1IHOPControl.cpp index 5c05169c29ded..c166e9d0914d1 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp @@ -50,6 +50,12 @@ void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t addi _last_allocation_time_s = allocation_time_s; } +size_t G1IHOPControl::default_conc_mark_start_threshold() { + guarantee(_target_occupancy > 0, "Target occupancy must have been initialized."); + size_t actual_target_occupancy = MIN2(G1CollectedHeap::heap()->soft_max_capacity(), _target_occupancy); + return (size_t) (_initial_ihop_percent * actual_target_occupancy / 100.0); +} + void G1IHOPControl::print() { assert(_target_occupancy > 0, "Target occupancy still not updated yet."); size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); @@ -109,7 +115,7 @@ size_t G1AdaptiveIHOPControl::actual_target_threshold() const { double safe_total_heap_percentage = MIN2((double)(_heap_reserve_percent + _heap_waste_percent), 100.0); return (size_t)MIN2( - G1CollectedHeap::heap()->max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, + G1CollectedHeap::heap()->soft_max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, _target_occupancy * (100.0 - _heap_waste_percent) / 100.0 ); } @@ -142,7 +148,7 @@ size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() { return predicted_initiating_threshold; } else { // Use the initial value. - return (size_t)(_initial_ihop_percent * _target_occupancy / 100.0); + return default_conc_mark_start_threshold(); } } diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.hpp b/src/hotspot/share/gc/g1/g1IHOPControl.hpp index 507fbb269d1d6..8b763a36f84db 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp @@ -55,6 +55,10 @@ class G1IHOPControl : public CHeapObj { // Most recent time from the end of the concurrent start to the start of the first // mixed gc. virtual double last_marking_length_s() const = 0; + + // Default non-young occupancy at which concurrent marking should start. + size_t default_conc_mark_start_threshold(); + public: virtual ~G1IHOPControl() { } @@ -92,8 +96,7 @@ class G1StaticIHOPControl : public G1IHOPControl { G1StaticIHOPControl(double ihop_percent, G1OldGenAllocationTracker const* old_gen_alloc_tracker); size_t get_conc_mark_start_threshold() { - guarantee(_target_occupancy > 0, "Target occupancy must have been initialized."); - return (size_t) (_initial_ihop_percent * _target_occupancy / 100.0); + return default_conc_mark_start_threshold(); } virtual void update_marking_length(double marking_length_s) { From 59d1ac6981d2eac4cb1e5441828d16f55ef67671 Mon Sep 17 00:00:00 2001 From: Man Cao Date: Tue, 25 Mar 2025 23:37:08 -0700 Subject: [PATCH 2/7] Update copyright year. --- src/hotspot/share/gc/g1/g1IHOPControl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.hpp b/src/hotspot/share/gc/g1/g1IHOPControl.hpp index 8b763a36f84db..e078d10093001 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.hpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From fc22cbfe2835ef510163d840b41b3036c126924a Mon Sep 17 00:00:00 2001 From: Man Cao Date: Tue, 1 Apr 2025 08:29:36 +0000 Subject: [PATCH 3/7] Add two tests --- .../jtreg/gc/g1/TestSoftMaxHeapSize.java | 81 +++++++++++++++++++ .../jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java | 81 +++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java create mode 100644 test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java new file mode 100644 index 0000000000000..17a5ed6b2036d --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.g1; + +/* + * @test + * @bug 8236073 + * @requires vm.gc.G1 & vm.opt.ExplicitGCInvokesConcurrent != true + * @library /test/lib + * @run main/othervm -Xmx200m -XX:MinHeapSize=4m -XX:MinHeapFreeRatio=99 + -XX:MaxHeapFreeRatio=99 gc.g1.TestSoftMaxHeapSize + * @summary Test that SoftMaxHeapSize could limit G1's heap size when resizing. + */ + +import java.lang.management.ManagementFactory; +import java.util.LinkedList; +import java.util.List; +import jdk.test.lib.dcmd.PidJcmdExecutor; + +public class TestSoftMaxHeapSize { + + private static final int OBJECT_SIZE = 1000; + private static final long ALLOCATED_BYTES = 20_000_000; // About 20M + private static final long MAX_HEAP_SIZE = + 200 * 1024 * 1024; // 200MiB, must match -Xmx on command line. + + private static final long SOFT_MAX_HEAP = + 30 * 1024 * 1024; // 30MiB, leaving ~10MiB headroom above ALLOCATED_BYTES. + + private static final List holder = new LinkedList<>(); + + private static long getCurrentHeapSize() { + return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getCommitted(); + } + + public static void main(String[] args) throws Exception { + + long count = ALLOCATED_BYTES / OBJECT_SIZE; + for (long i = 0; i < count; ++i) { + holder.add(new byte[OBJECT_SIZE]); + } + + System.gc(); + long heapSize = getCurrentHeapSize(); + if (heapSize != MAX_HEAP_SIZE) { + throw new RuntimeException( + "Heap size did not fully expand to Xmx after full GC: heapSize = " + heapSize); + } + + PidJcmdExecutor jcmd = new PidJcmdExecutor(); + jcmd.execute("VM.set_flag SoftMaxHeapSize " + SOFT_MAX_HEAP, true); + + System.gc(); + heapSize = getCurrentHeapSize(); + if (heapSize != SOFT_MAX_HEAP) { + throw new RuntimeException( + "Heap size did not shrink to SoftMaxHeapSize after full GC: heapSize = " + heapSize); + } + } +} diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java new file mode 100644 index 0000000000000..ea75b8ad612b4 --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.g1; + +/* + * @test id=normal + * @bug 8236073 8352765 + * @requires vm.gc.G1 + * @library /test/lib + * @run main/othervm -Xmx100m -XX:MinHeapSize=4m -XX:SoftMaxHeapSize=4m + gc.g1.TestSoftMaxHeapSizeNoOOM + * @summary Test that setting TestSoftMaxHeapSize to a small value won't + * trigger OutOfMemoryError for normal allocations. + */ + +/* + * @test id=humongous + * @bug 8236073 8352765 + * @requires vm.gc.G1 + * @library /test/lib + * @run main/othervm -Xmx100m -XX:MinHeapSize=4m -XX:SoftMaxHeapSize=4m + -Dhumongous=true gc.g1.TestSoftMaxHeapSizeNoOOM + * @summary Test that setting TestSoftMaxHeapSize to a small value won't + * trigger OutOfMemoryError for humongous allocations. + */ + +import java.util.ArrayList; + +public class TestSoftMaxHeapSizeNoOOM { + + private static final long ALLOCATED_BYTES = 20_000_000; // About 20M + private static final int OBJECT_SIZE = 1000; + private static final int ITERATIONS = 100000; + private static final int HUMONGOUS_OBJECT_SIZE = 1_500_000; // About 1.5M + private static final int HUMONGOUS_ITERATIONS = 1000; + + private static final ArrayList holder = new ArrayList<>(); + + private static void work(int objSize, int iterations) { + long count = ALLOCATED_BYTES / objSize; + for (long i = 0; i < count; ++i) { + holder.add(new byte[objSize]); + } + // Mutate old objects while allocating new objects. + // This is effective to trigger concurrent collections for G1, + // and is necessary to reproduce OutOfMemoryError in JDK-8352765. + for (long i = 0; i < iterations; ++i) { + holder.remove(0); + holder.add(new byte[objSize]); + } + } + + public static void main(String[] args) throws Exception { + if (Boolean.getBoolean("humongous")) { + work(HUMONGOUS_OBJECT_SIZE, HUMONGOUS_ITERATIONS); + } else { + work(OBJECT_SIZE, ITERATIONS); + } + } +} From 68f03cadb33df01b810fb46b646f25ad694369a0 Mon Sep 17 00:00:00 2001 From: Man Cao Date: Tue, 1 Apr 2025 08:37:34 +0000 Subject: [PATCH 4/7] Revise test summary --- test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java | 2 +- test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java index 17a5ed6b2036d..905945905faf0 100644 --- a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java @@ -30,7 +30,7 @@ * @library /test/lib * @run main/othervm -Xmx200m -XX:MinHeapSize=4m -XX:MinHeapFreeRatio=99 -XX:MaxHeapFreeRatio=99 gc.g1.TestSoftMaxHeapSize - * @summary Test that SoftMaxHeapSize could limit G1's heap size when resizing. + * @summary SoftMaxHeapSize should limit G1's heap size when resizing. */ import java.lang.management.ManagementFactory; diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java index ea75b8ad612b4..4011deecbf798 100644 --- a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSizeNoOOM.java @@ -30,8 +30,8 @@ * @library /test/lib * @run main/othervm -Xmx100m -XX:MinHeapSize=4m -XX:SoftMaxHeapSize=4m gc.g1.TestSoftMaxHeapSizeNoOOM - * @summary Test that setting TestSoftMaxHeapSize to a small value won't - * trigger OutOfMemoryError for normal allocations. + * @summary Setting SoftMaxHeapSize to a small value won't trigger + * OutOfMemoryError for normal allocations. */ /* @@ -41,8 +41,8 @@ * @library /test/lib * @run main/othervm -Xmx100m -XX:MinHeapSize=4m -XX:SoftMaxHeapSize=4m -Dhumongous=true gc.g1.TestSoftMaxHeapSizeNoOOM - * @summary Test that setting TestSoftMaxHeapSize to a small value won't - * trigger OutOfMemoryError for humongous allocations. + * @summary Setting SoftMaxHeapSize to a small value won't trigger + * OutOfMemoryError for humongous allocations. */ import java.util.ArrayList; From 0bc55654dfdfbfc462e54fa96c38f46f729e5989 Mon Sep 17 00:00:00 2001 From: Man Cao Date: Tue, 1 Apr 2025 13:48:37 -0700 Subject: [PATCH 5/7] Address comments and try fixing test failure on macos-aarch64 --- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 4 ++-- src/hotspot/share/gc/g1/g1IHOPControl.cpp | 5 +++-- test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java | 10 ++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 990074d3687ca..abdbcae2a08ea 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -1197,10 +1197,10 @@ class G1CollectedHeap : public CollectedHeap { // requires. static size_t humongous_obj_size_in_regions(size_t word_size); - // Print the maximum heap capacity. + // Returns the maximum heap capacity. size_t max_capacity() const override; - // Print the soft maximum heap capacity. + // Returns the soft maximum heap capacity. size_t soft_max_capacity() const; Tickspan time_since_last_collection() const { return Ticks::now() - _collection_pause_end; } diff --git a/src/hotspot/share/gc/g1/g1IHOPControl.cpp b/src/hotspot/share/gc/g1/g1IHOPControl.cpp index c166e9d0914d1..aacff5ad38882 100644 --- a/src/hotspot/share/gc/g1/g1IHOPControl.cpp +++ b/src/hotspot/share/gc/g1/g1IHOPControl.cpp @@ -114,8 +114,9 @@ size_t G1AdaptiveIHOPControl::actual_target_threshold() const { double safe_total_heap_percentage = MIN2((double)(_heap_reserve_percent + _heap_waste_percent), 100.0); - return (size_t)MIN2( - G1CollectedHeap::heap()->soft_max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, + return (size_t)MIN3( + G1CollectedHeap::heap()->max_capacity() * (100.0 - safe_total_heap_percentage) / 100.0, + static_cast(G1CollectedHeap::heap()->soft_max_capacity()), _target_occupancy * (100.0 - _heap_waste_percent) / 100.0 ); } diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java index 905945905faf0..d66eafaddb5dd 100644 --- a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java @@ -26,7 +26,8 @@ /* * @test * @bug 8236073 - * @requires vm.gc.G1 & vm.opt.ExplicitGCInvokesConcurrent != true + * @requires vm.gc.G1 + * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib * @run main/othervm -Xmx200m -XX:MinHeapSize=4m -XX:MinHeapFreeRatio=99 -XX:MaxHeapFreeRatio=99 gc.g1.TestSoftMaxHeapSize @@ -42,11 +43,8 @@ public class TestSoftMaxHeapSize { private static final int OBJECT_SIZE = 1000; private static final long ALLOCATED_BYTES = 20_000_000; // About 20M - private static final long MAX_HEAP_SIZE = - 200 * 1024 * 1024; // 200MiB, must match -Xmx on command line. - private static final long SOFT_MAX_HEAP = - 30 * 1024 * 1024; // 30MiB, leaving ~10MiB headroom above ALLOCATED_BYTES. + 50 * 1024 * 1024; // 50MiB, leaving ~30MiB headroom above ALLOCATED_BYTES. private static final List holder = new LinkedList<>(); @@ -63,7 +61,7 @@ public static void main(String[] args) throws Exception { System.gc(); long heapSize = getCurrentHeapSize(); - if (heapSize != MAX_HEAP_SIZE) { + if (heapSize != ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()) { throw new RuntimeException( "Heap size did not fully expand to Xmx after full GC: heapSize = " + heapSize); } From 4435e89ffcb9decbcddc320af5da9734ec63849a Mon Sep 17 00:00:00 2001 From: Man Cao Date: Wed, 2 Apr 2025 10:03:21 +0000 Subject: [PATCH 6/7] Fix test failure on macos-aarch64 by using power-of-two sizes. --- test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java index d66eafaddb5dd..ee4563f118bb5 100644 --- a/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/g1/TestSoftMaxHeapSize.java @@ -29,7 +29,7 @@ * @requires vm.gc.G1 * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib - * @run main/othervm -Xmx200m -XX:MinHeapSize=4m -XX:MinHeapFreeRatio=99 + * @run main/othervm -Xmx256m -XX:MinHeapSize=4m -XX:MinHeapFreeRatio=99 -XX:MaxHeapFreeRatio=99 gc.g1.TestSoftMaxHeapSize * @summary SoftMaxHeapSize should limit G1's heap size when resizing. */ @@ -43,8 +43,10 @@ public class TestSoftMaxHeapSize { private static final int OBJECT_SIZE = 1000; private static final long ALLOCATED_BYTES = 20_000_000; // About 20M + + // Uses power-of-two value so it is aligned and is the actual effective value. private static final long SOFT_MAX_HEAP = - 50 * 1024 * 1024; // 50MiB, leaving ~30MiB headroom above ALLOCATED_BYTES. + 32 * 1024 * 1024; // 32MiB, leaving ~12MiB headroom above ALLOCATED_BYTES. private static final List holder = new LinkedList<>(); From c60ade41c4c07079b0a1331eb8ba9293a14585ee Mon Sep 17 00:00:00 2001 From: Man Cao Date: Thu, 3 Apr 2025 07:05:04 +0000 Subject: [PATCH 7/7] Use Atomic::load for flag --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 5115108a8b9c2..9095a3e2a376d 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2062,7 +2062,7 @@ size_t G1CollectedHeap::max_capacity() const { } size_t G1CollectedHeap::soft_max_capacity() const { - return clamp(align_up(SoftMaxHeapSize, HeapAlignment), MinHeapSize, + return clamp(align_up(Atomic::load(&SoftMaxHeapSize), HeapAlignment), MinHeapSize, max_capacity()); }