|
1 | 1 | /* |
2 | | - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
|
28 | 28 | * @bug 8051973 |
29 | 29 | * @summary Test to make sure that eager reclaim of humongous objects correctly clears |
30 | 30 | * mark bitmaps at reclaim. |
31 | | - * @key randomness |
32 | 31 | * @requires vm.gc.G1 |
33 | 32 | * @requires vm.debug |
34 | | - * @library /test/lib |
| 33 | + * @library /test/lib /testlibrary / |
35 | 34 | * @modules java.base/jdk.internal.misc |
36 | 35 | * java.management |
| 36 | + * @build jdk.test.whitebox.WhiteBox |
| 37 | + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox |
37 | 38 | * @run driver gc.g1.TestEagerReclaimHumongousRegionsClearMarkBits |
38 | 39 | */ |
39 | 40 |
|
40 | | -import java.util.ArrayList; |
41 | | -import java.util.LinkedList; |
42 | | -import java.util.Random; |
| 41 | +import java.util.regex.Matcher; |
| 42 | +import java.util.regex.Pattern; |
43 | 43 |
|
| 44 | +import jdk.test.lib.Asserts; |
44 | 45 | import jdk.test.lib.process.OutputAnalyzer; |
45 | 46 | import jdk.test.lib.process.ProcessTools; |
46 | | -import jdk.test.lib.Utils; |
47 | | - |
48 | | -// An object that has a few references to other instances to slow down marking. |
49 | | -class ObjectWithSomeRefs { |
50 | | - public ObjectWithSomeRefs other1; |
51 | | - public ObjectWithSomeRefs other2; |
52 | | - public ObjectWithSomeRefs other3; |
53 | | - public ObjectWithSomeRefs other4; |
54 | | -} |
55 | | - |
56 | | -class TestEagerReclaimHumongousRegionsClearMarkBitsReclaimRegionFast { |
57 | | - public static final long MAX_NANOS_FOR_RUN = 50L * 1_000_000_000L; // The maximum runtime for the actual test. |
| 47 | +import jdk.test.whitebox.WhiteBox; |
58 | 48 |
|
59 | | - public static final int M = 1024*1024; |
| 49 | +public class TestEagerReclaimHumongousRegionsClearMarkBits { |
| 50 | + public static void main(String[] args) throws Exception { |
| 51 | + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", |
| 52 | + "-Xmx20M", |
| 53 | + "-Xms20m", |
| 54 | + "-XX:+UnlockDiagnosticVMOptions", |
| 55 | + "-XX:+VerifyAfterGC", |
| 56 | + "-Xbootclasspath/a:.", |
| 57 | + "-Xlog:gc=debug,gc+humongous=debug", |
| 58 | + "-XX:+UnlockDiagnosticVMOptions", |
| 59 | + "-XX:+WhiteBoxAPI", |
| 60 | + TestEagerReclaimHumongousRegionsClearMarkBitsRunner.class.getName()); |
| 61 | + |
| 62 | + String log = output.getStdout(); |
| 63 | + System.out.println(log); |
| 64 | + output.shouldHaveExitValue(0); |
60 | 65 |
|
61 | | - public static LinkedList<Object> garbageList = new LinkedList<Object>(); |
| 66 | + // Find the log output indicating that the humongous object has been reclaimed, and marked. |
| 67 | + Pattern pattern = Pattern.compile("Humongous region .* marked 1 .* reclaim candidate 1 type array 1"); |
| 68 | + Asserts.assertTrue(pattern.matcher(log).find(), "Could not find log output matching marked humongous region."); |
62 | 69 |
|
63 | | - public static void genGarbage(Object large) { |
64 | | - for (int i = 0; i < 64*1024; i++) { |
65 | | - Object[] garbage = new Object[50]; |
66 | | - garbage[0] = large; |
67 | | - garbageList.add(garbage); |
68 | | - } |
69 | | - garbageList.clear(); |
| 70 | + pattern = Pattern.compile("Reclaimed humongous region .*"); |
| 71 | + Asserts.assertTrue(pattern.matcher(log).find(), "Could not find log output reclaiming humongous region"); |
70 | 72 | } |
| 73 | +} |
71 | 74 |
|
72 | | - public static ArrayList<ObjectWithSomeRefs> longList = new ArrayList<ObjectWithSomeRefs>(); |
| 75 | +class TestEagerReclaimHumongousRegionsClearMarkBitsRunner { |
| 76 | + private static final WhiteBox WB = WhiteBox.getWhiteBox(); |
| 77 | + private static final int M = 1024 * 1024; |
73 | 78 |
|
74 | 79 | public static void main(String[] args) { |
| 80 | + WB.fullGC(); |
75 | 81 |
|
76 | | - for (int i = 0; i < 16*1024; i++) { |
77 | | - longList.add(new ObjectWithSomeRefs()); |
78 | | - } |
79 | | - |
80 | | - Random rnd = Utils.getRandomInstance(); |
81 | | - for (int i = 0; i < longList.size(); i++) { |
82 | | - int len = longList.size(); |
83 | | - longList.get(i).other1 = longList.get(rnd.nextInt(len)); |
84 | | - longList.get(i).other2 = longList.get(rnd.nextInt(len)); |
85 | | - longList.get(i).other3 = longList.get(rnd.nextInt(len)); |
86 | | - longList.get(i).other4 = longList.get(rnd.nextInt(len)); |
87 | | - } |
88 | | - |
89 | | - int[] large1 = new int[M]; |
90 | | - int[] large2 = null; |
91 | | - int[] large3 = null; |
92 | | - int[] large4 = null; |
93 | | - |
94 | | - Object ref_from_stack = large1; |
95 | | - |
96 | | - long start_nanos = System.nanoTime(); |
97 | | - |
98 | | - for (int i = 0; i < 20; i++) { |
99 | | - long current_nanos = System.nanoTime(); |
100 | | - if ((current_nanos - start_nanos) > MAX_NANOS_FOR_RUN) { |
101 | | - System.out.println("Finishing test because maximum runtime exceeded"); |
102 | | - break; |
103 | | - } |
104 | | - // A set of large objects that will be reclaimed eagerly - and hopefully marked. |
105 | | - large1 = new int[M - 20]; |
106 | | - large2 = new int[M - 20]; |
107 | | - large3 = new int[M - 20]; |
108 | | - large4 = new int[M - 20]; |
109 | | - genGarbage(large1); |
110 | | - // Make sure that the compiler cannot completely remove |
111 | | - // the allocation of the large object until here. |
112 | | - System.out.println(large1 + " " + large2 + " " + large3 + " " + large4); |
113 | | - } |
114 | | - |
115 | | - // Keep the reference to the first object alive. |
116 | | - System.out.println(ref_from_stack); |
117 | | - } |
118 | | -} |
| 82 | + Object largeObj = new int[M]; // Humongous object. |
119 | 83 |
|
120 | | -public class TestEagerReclaimHumongousRegionsClearMarkBits { |
121 | | - public static void main(String[] args) throws Exception { |
122 | | - OutputAnalyzer output = ProcessTools.executeLimitedTestJava( |
123 | | - "-XX:+UseG1GC", |
124 | | - "-Xms128M", |
125 | | - "-Xmx128M", |
126 | | - "-Xmn2M", |
127 | | - "-XX:G1HeapRegionSize=1M", |
128 | | - "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible mark cycles. |
129 | | - "-Xlog:gc", |
130 | | - "-XX:+UnlockDiagnosticVMOptions", |
131 | | - "-XX:+VerifyAfterGC", |
132 | | - "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. |
133 | | - "-XX:+G1VerifyBitmaps", |
134 | | - TestEagerReclaimHumongousRegionsClearMarkBitsReclaimRegionFast.class.getName()); |
135 | | - output.shouldHaveExitValue(0); |
| 84 | + WB.concurrentGCAcquireControl(); |
| 85 | + WB.concurrentGCRunTo(WB.BEFORE_MARKING_COMPLETED); |
| 86 | + |
| 87 | + System.out.println("Large object at " + largeObj); |
| 88 | + |
| 89 | + largeObj = null; |
| 90 | + WB.youngGC(); // Should reclaim marked humongous object. |
| 91 | + |
| 92 | + WB.concurrentGCRunToIdle(); |
136 | 93 | } |
137 | 94 | } |
| 95 | + |
0 commit comments