1 /*
2 * Copyright Amazon.com Inc. 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
25 package jdk.jfr.event.gc.detailed;
26
27 import java.time.Duration;
28 import java.util.List;
29 import java.util.Random;
30
31 import jdk.jfr.Recording;
32 import jdk.jfr.consumer.RecordedEvent;
33 import jdk.test.lib.Asserts;
34 import jdk.test.lib.jfr.EventNames;
35 import jdk.test.lib.jfr.Events;
36 import jdk.test.lib.jfr.GCHelper;
37
38 /**
39 * @test
40 * @bug 8221507
41 * @requires vm.hasJFR & vm.gc.Shenandoah
42 * @key jfr
43 * @library /test/lib /test/jdk
44 * @run main/othervm -Xmx64m -XX:+UnlockExperimentalVMOptions -XX:ShenandoahRegionSize=1m -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational jdk.jfr.event.gc.detailed.TestShenandoahEvacuationInformationEvent
45 */
46
47 public class TestShenandoahEvacuationInformationEvent {
48 private final static String EVENT_NAME = EventNames.ShenandoahEvacuationInformation;
49
50 public static void main(String[] args) throws Exception {
51 final long shenandoahHeapRegionSize = 1024 * 1024;
52 final long shenandoahMaxHeapRegionCount = 64;
53 Recording recording = new Recording();
54 recording.enable(EVENT_NAME).withThreshold(Duration.ofMillis(0));
55 recording.start();
56 allocate();
57 recording.stop();
58
59 List<RecordedEvent> events = Events.fromRecording(recording);
60 Asserts.assertFalse(events.isEmpty(), "No events found");
61 for (RecordedEvent event : events) {
62 if (!Events.isEventType(event, EVENT_NAME)) {
63 continue;
64 }
65 System.out.println("Event: " + event);
66
67 long cSetRegions = Events.assertField(event, "cSetRegions").atLeast(0L).getValue();
68 long setUsedAfter = Events.assertField(event, "cSetUsedAfter").atLeast(0L).getValue();
69 long setUsedBefore = Events.assertField(event, "cSetUsedBefore").atLeast(setUsedAfter).getValue();
70 long freeRegions = Events.assertField(event, "freeRegions").atLeast(0L).getValue();
71 Events.assertField(event, "collectedOld").atLeast(0L).getValue();
72 Events.assertField(event, "collectedYoung").atLeast(0L).getValue();
73
74 Asserts.assertGreaterThanOrEqual(shenandoahMaxHeapRegionCount, freeRegions + cSetRegions, "numRegions >= freeRegions + cSetRegions");
75 Asserts.assertGreaterThanOrEqual(shenandoahHeapRegionSize * cSetRegions, setUsedAfter, "ShenandoahHeapRegionSize * cSetRegions >= setUsedAfter");
76 Asserts.assertGreaterThanOrEqual(shenandoahHeapRegionSize * cSetRegions, setUsedBefore, "ShenandoahHeapRegionSize * cSetRegions >= setUsedBefore");
77
78 int gcId = Events.assertField(event, "gcId").getValue();
79 }
80 }
81
82 /**
83 * Allocate memory to trigger garbage collections.
84 * We want the allocated objects to have different life time, because we want both "young" and "old" objects.
85 * This is done by keeping the objects in an array and step the current index by a small random number in the loop.
86 * The loop will continue until we have allocated a fixed number of bytes.
87 */
88 private static void allocate() {
89 DummyObject[] dummys = new DummyObject[6000];
90
91 Random r = new Random(0);
92 long bytesToAllocate = 256 * 1024 * 1024;
93 int currPos = 0;
94 while (bytesToAllocate > 0) {
95 int allocSize = 1000 + (r.nextInt(4000));
96 bytesToAllocate -= allocSize;
97 dummys[currPos] = new DummyObject(allocSize);
98
99 // Skip a few positions to get different duration on the objects.
100 currPos = (currPos + r.nextInt(20)) % dummys.length;
101 }
102 for (int c=0; c<dummys.length; c++) {
103 dummys[c] = null;
104 }
105 System.gc();
106 }
107
108 public static class DummyObject {
109 public byte[] payload;
110 DummyObject(int size) {
111 payload = new byte[size];
112 }
113 }
114 }