Skip to content

Commit 72fbfe1

Browse files
Thomas SchatzlAndreas Steiner
andcommitted
8330577: G1 sometimes sends jdk.G1HeapRegionTypeChange for non-changes
Co-authored-by: Andreas Steiner <[email protected]> Reviewed-by: ayang, asteiner
1 parent 0889155 commit 72fbfe1

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ double G1HeapRegion::calc_gc_efficiency() {
150150
}
151151

152152
void G1HeapRegion::set_free() {
153-
report_region_type_change(G1HeapRegionTraceType::Free);
153+
if (!is_free()) {
154+
report_region_type_change(G1HeapRegionTraceType::Free);
155+
}
154156
_type.set_free();
155157
}
156158

@@ -170,8 +172,9 @@ void G1HeapRegion::set_survivor() {
170172
}
171173

172174
void G1HeapRegion::move_to_old() {
175+
G1HeapRegionTraceType::Type prev_trace_type = _type.get_trace_type();
173176
if (_type.relabel_as_old()) {
174-
report_region_type_change(G1HeapRegionTraceType::Old);
177+
report_region_type_change(prev_trace_type);
175178
}
176179
}
177180

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2024, 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+
package jdk.jfr.event.gc.detailed;
24+
25+
import java.nio.file.Paths;
26+
import java.time.Duration;
27+
import java.util.List;
28+
29+
import jdk.jfr.Recording;
30+
import jdk.jfr.consumer.RecordedEvent;
31+
import jdk.test.lib.Asserts;
32+
import jdk.test.lib.jfr.EventNames;
33+
import jdk.test.lib.jfr.Events;
34+
import jdk.test.lib.jfr.GCHelper;
35+
36+
/**
37+
* @test
38+
* @bug 8330577
39+
* @requires vm.hasJFR
40+
* @requires vm.gc == "G1" | vm.gc == null
41+
* @requires vm.debug
42+
* @key jfr
43+
* @library /test/lib /test/jdk
44+
* @summary Make sure that there are no Old->Old and Free->Free events sent.
45+
* @run main/othervm -XX:+G1GCAllocationFailureALot -XX:NewSize=2m -XX:MaxNewSize=2m -XX:MaxTenuringThreshold=1
46+
* -Xmx32m -XX:G1HeapRegionSize=1m -XX:+UseG1GC -Xlog:gc jdk.jfr.event.gc.detailed.TestG1InvalidHeapRegionTypeChangeEvent
47+
*/
48+
49+
public class TestG1InvalidHeapRegionTypeChangeEvent {
50+
private final static String EVENT_NAME = EventNames.G1HeapRegionTypeChange;
51+
52+
public static void main(String[] args) throws Exception {
53+
Recording recording = null;
54+
try {
55+
recording = new Recording();
56+
// activate the event we are interested in and start recording
57+
recording.enable(EVENT_NAME).withThreshold(Duration.ofMillis(0));
58+
recording.start();
59+
60+
// Compact the heap, creating some Old regions. Previously this sent
61+
// Free->Free transitions too.
62+
System.gc();
63+
64+
// Setting NewSize and MaxNewSize will limit eden, so
65+
// allocating 1024 20k byte arrays should trigger at
66+
// least a few Young GCs.
67+
// This fragments the heap a little (together with
68+
// G1GCAllocationFailureALot), so that the next Full GC
69+
// will generate Free -> Old transitions that were incorrectly
70+
// sent as Old -> Old.
71+
// Note that an Old -> Old transition is actually valid in case
72+
// of evacuation failure in an old region, but this is no
73+
// change of region and should not be sent either.
74+
75+
byte[][] array = new byte[1024][];
76+
for (int i = 0; i < array.length; i++) {
77+
array[i] = new byte[20 * 1024];
78+
}
79+
80+
System.gc();
81+
recording.stop();
82+
83+
// Verify recording
84+
List<RecordedEvent> events = Events.fromRecording(recording);
85+
Asserts.assertFalse(events.isEmpty(), "No events found");
86+
87+
for (RecordedEvent event : events) {
88+
Events.assertField(event, "index").notEqual(-1);
89+
Asserts.assertTrue(GCHelper.isValidG1HeapRegionType(Events.assertField(event, "from").getValue()));
90+
Asserts.assertTrue(GCHelper.isValidG1HeapRegionType(Events.assertField(event, "to").getValue()));
91+
Events.assertField(event, "used").atMost(1L*1024*1024);
92+
// There should be no Old->Old and Free->Free "changes".
93+
Asserts.assertFalse(Events.assertField(event, "from").getValue().equals("Old") && Events.assertField(event, "to").getValue().equals("Old"));
94+
Asserts.assertFalse(Events.assertField(event, "from").getValue().equals("Free") && Events.assertField(event, "to").getValue().equals("Free"));
95+
}
96+
} catch (Throwable t) {
97+
if (recording != null) {
98+
recording.dump(Paths.get("TestG1HeapRegionTypeChangeEvent.jfr"));
99+
}
100+
throw t;
101+
} finally {
102+
if (recording != null) {
103+
recording.close();
104+
}
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)