Skip to content

Commit de4dec1

Browse files
author
Thomas Schatzl
committed
8386332: G1: Cleanup pause incorrectly updates old gen MemoryPoolMXBean.getCollectionUsage()
Reviewed-by: ayang, iwalulya
1 parent fd57723 commit de4dec1

5 files changed

Lines changed: 119 additions & 8 deletions

File tree

src/hotspot/share/gc/g1/g1MonitoringSupport.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -201,7 +201,7 @@ void G1MonitoringSupport::initialize_serviceability() {
201201
_full_gc_memory_manager.add_pool(_survivor_space_pool);
202202
_full_gc_memory_manager.add_pool(_old_gen_pool);
203203

204-
_conc_gc_memory_manager.add_pool(_old_gen_pool);
204+
_conc_gc_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */);
205205

206206
_young_gc_memory_manager.add_pool(_eden_space_pool);
207207
_young_gc_memory_manager.add_pool(_survivor_space_pool);
@@ -383,9 +383,10 @@ G1FullGCMonitoringScope::G1FullGCMonitoringScope(G1MonitoringSupport* monitoring
383383
"end of major GC") {
384384
}
385385

386-
G1ConcGCMonitoringScope::G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support) :
386+
G1ConcGCMonitoringScope::G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support, bool affects_memory_pools) :
387387
G1MonitoringScope(monitoring_support,
388388
monitoring_support->_conc_collection_counters,
389389
&monitoring_support->_conc_gc_memory_manager,
390-
"end of concurrent GC pause") {
390+
"end of concurrent GC pause",
391+
affects_memory_pools) {
391392
}

src/hotspot/share/gc/g1/g1MonitoringSupport.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -246,6 +246,6 @@ class G1FullGCMonitoringScope : public G1MonitoringScope {
246246

247247
class G1ConcGCMonitoringScope : public G1MonitoringScope {
248248
public:
249-
G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support);
249+
G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support, bool affects_memory_pools);
250250
};
251251
#endif // SHARE_GC_G1_G1MONITORINGSUPPORT_HPP

src/hotspot/share/gc/g1/g1VMOperations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void VM_G1PauseConcurrent::doit() {
140140
GCTraceTimePauseTimer timer(_message, g1h->concurrent_mark()->gc_timer_cm());
141141
GCTraceTimeDriver t(&logger, &timer);
142142

143-
G1ConcGCMonitoringScope monitoring_scope(g1h->monitoring_support());
143+
G1ConcGCMonitoringScope monitoring_scope(g1h->monitoring_support(), affects_memory_pools());
144144
SvcGCMarker sgcm(SvcGCMarker::CONCURRENT);
145145
IsSTWGCActiveMark x;
146146

src/hotspot/share/gc/g1/g1VMOperations.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,10 @@ class VM_G1PauseConcurrent : public VM_Operation {
8787
_gc_id(GCId::current()), _message(message) { }
8888
virtual void work() = 0;
8989

90+
// Does this concurrent pause affect the memory pools? If so, update the collectionUsage()
91+
// MemoryMXBean for the old gen memory pool (which is the only pool registered for concurrent
92+
// pauses).
93+
virtual bool affects_memory_pools() const = 0;
9094
public:
9195
bool doit_prologue() override;
9296
void doit_epilogue() override;
@@ -95,13 +99,17 @@ class VM_G1PauseConcurrent : public VM_Operation {
9599
};
96100

97101
class VM_G1PauseRemark : public VM_G1PauseConcurrent {
102+
bool affects_memory_pools() const override { return true; }
103+
98104
public:
99105
VM_G1PauseRemark() : VM_G1PauseConcurrent("Pause Remark") { }
100106
VMOp_Type type() const override { return VMOp_G1PauseRemark; }
101107
void work() override;
102108
};
103109

104110
class VM_G1PauseCleanup : public VM_G1PauseConcurrent {
111+
bool affects_memory_pools() const override { return false; }
112+
105113
public:
106114
VM_G1PauseCleanup() : VM_G1PauseConcurrent("Pause Cleanup") { }
107115
VMOp_Type type() const override { return VMOp_G1PauseCleanup; }
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package gc.g1;
25+
26+
/*
27+
* @test TestRemarkCleanupMXBeanCollectionUsage
28+
* @bug 8386332
29+
* @summary Test that Remark and Cleanup correctly update old pool's getCollectionUsage() bean.
30+
* @requires vm.gc.G1
31+
* @library /test/lib /
32+
* @build jdk.test.whitebox.WhiteBox
33+
* @modules java.base/jdk.internal.misc
34+
* java.management
35+
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
36+
* @run main/othervm -XX:+UseG1GC -Xlog:gc -XX:G1HeapRegionSize=1m -Xms128m -Xmx128m
37+
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
38+
* gc.g1.TestRemarkCleanupMXBeanCollectionUsage
39+
*/
40+
41+
import java.lang.management.ManagementFactory;
42+
import java.lang.management.MemoryPoolMXBean;
43+
import java.lang.management.MemoryUsage;
44+
import java.lang.ref.Reference;
45+
46+
import jdk.test.lib.Asserts;
47+
import jdk.test.whitebox.WhiteBox;
48+
49+
public class TestRemarkCleanupMXBeanCollectionUsage {
50+
private static WhiteBox wb = WhiteBox.getWhiteBox();
51+
private static final int M = 1024 * 1024;
52+
53+
private static MemoryPoolMXBean findPoolMXBean(String name) throws Exception {
54+
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
55+
if (pool.getName().equals(name)) {
56+
return pool;
57+
}
58+
}
59+
throw new RuntimeException("Pool " + name + " not found.");
60+
}
61+
62+
private static long getCollectionUsageUsedAndPrint(MemoryPoolMXBean pool, String message) {
63+
long result = pool.getCollectionUsage().getUsed();
64+
System.out.println(message + ": " + result);
65+
return result;
66+
}
67+
68+
public static void main(String[] args) throws Exception {
69+
Object throwaway = new Object();
70+
try {
71+
MemoryPoolMXBean oldPool = findPoolMXBean("G1 Old Gen");
72+
73+
wb.concurrentGCAcquireControl();
74+
wb.fullGC();
75+
long initialUsage = getCollectionUsageUsedAndPrint(oldPool, "Initial Usage");
76+
77+
// Allocate something in old gen. CollectionUsage should be updated.
78+
throwaway = new byte[M]; // Humongous allocation.
79+
wb.fullGC();
80+
long afterFirstUsage = getCollectionUsageUsedAndPrint(oldPool, "After first alloc usage");
81+
Asserts.assertTrue(afterFirstUsage >= initialUsage + M,
82+
"Full GC should updated collectionUsage. Before " + afterFirstUsage + " after " + initialUsage);
83+
84+
// Remark pause should update collectionUsage, i.e. the following release of the memory be noticed.
85+
throwaway = null;
86+
wb.concurrentGCRunTo(wb.G1_AFTER_REBUILD_STARTED);
87+
long afterRemarkUsage = getCollectionUsageUsedAndPrint(oldPool, "After Remark usage");
88+
Asserts.assertTrue(afterRemarkUsage < afterFirstUsage - M,
89+
"Remark pause should have updated getCollectionUsage(). Before " + afterFirstUsage + " after " + afterRemarkUsage);
90+
91+
// Cleanup pause should not update collectionUsage, i.e. the following allocation go unnoticed.
92+
throwaway = new byte[M];
93+
wb.concurrentGCRunTo(wb.G1_AFTER_CLEANUP_STARTED);
94+
long afterCleanupUsage = getCollectionUsageUsedAndPrint(oldPool, "After Cleanup usage");
95+
Asserts.assertTrue(afterCleanupUsage == afterRemarkUsage,
96+
"Cleanup pause should not update getCollectionUsage(). Before " + afterRemarkUsage + " after " + afterCleanupUsage);
97+
} finally {
98+
wb.concurrentGCReleaseControl();
99+
Reference.reachabilityFence(throwaway);
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)