1 /*
2 * Copyright Amazon.com Inc. 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.stress.ihash;
25
26 /*
27 * @test id=G1
28 * @bug 8387335
29 * @summary Stress test: does humongous object compaction corrupt hash-code or other objects?
30 * @requires vm.gc.G1
31 * @key stress
32 * @run main/othervm/timeout=300
33 * -XX:+UseCompactObjectHeaders -XX:+UseG1GC
34 * -XX:+UnlockDiagnosticVMOptions -XX:+VerifyDuringGC
35 * -XX:-ExplicitGCInvokesConcurrent
36 * -Xmx512m -XX:G1HeapRegionSize=1M
37 * gc.stress.ihash.TestHumongousHash
38 */
39
40 /*
41 * @test id=Shenandoah
42 * @bug 8387285
43 * @summary Stress test: does humongous object compaction corrupt hash-code or other objects?
44 * @requires vm.gc.Shenandoah
45 * @key stress
46 * @run main/othervm/timeout=300
47 * -XX:+UseCompactObjectHeaders -XX:+UseShenandoahGC
48 * -XX:+UnlockDiagnosticVMOptions -XX:+VerifyDuringGC
49 * -XX:-ExplicitGCInvokesConcurrent
50 * -Xmx512m
51 * -XX:+UnlockExperimentalVMOptions -XX:ShenandoahRegionSize=512K
52 * gc.stress.ihash.TestHumongousHash
53 */
54
55 /*
56 * @test id=Shenandoah-aggressive
57 * @bug 8387285
58 * @summary Stress test: does humongous object compaction corrupt hash-code or other objects?
59 * @requires vm.gc.Shenandoah
60 * @key stress
61 * @run main/othervm/timeout=300
62 * -XX:+UseCompactObjectHeaders -XX:+UseShenandoahGC
63 * -XX:+UnlockDiagnosticVMOptions -XX:+VerifyDuringGC
64 * -XX:-ExplicitGCInvokesConcurrent
65 * -XX:ShenandoahGCHeuristics=aggressive
66 * -Xmx512m
67 * -XX:+UnlockExperimentalVMOptions -XX:ShenandoahRegionSize=512K
68 * gc.stress.ihash.TestHumongousHash
69 */
70
71 /*
72 * @test id=Shenandoah-min-region
73 * @bug 8387285
74 * @summary Stress test at the minimum (256K) region size, where the hash-expansion
75 * humongous routing actually binds (an exact-region-multiple object needs
76 * N+1 regions after expansion).
77 * @requires vm.gc.Shenandoah
78 * @key stress
79 * @run main/othervm/timeout=300
80 * -XX:+UseCompactObjectHeaders -XX:+UseShenandoahGC
81 * -XX:+UnlockDiagnosticVMOptions -XX:+VerifyDuringGC
82 * -XX:-ExplicitGCInvokesConcurrent
83 * -Xmx512m
84 * -XX:+UnlockExperimentalVMOptions -XX:ShenandoahRegionSize=256K
85 * gc.stress.ihash.TestHumongousHash
86 */
87
88 /*
89 * @test id=Shenandoah-min-region-aggressive
90 * @bug 8387285
91 * @summary Stress test at the minimum (256K) region size, where the hash-expansion
92 * humongous routing actually binds (an exact-region-multiple object needs
93 * N+1 regions after expansion).
94 * @requires vm.gc.Shenandoah
95 * @key stress
96 * @run main/othervm/timeout=300
97 * -XX:+UseCompactObjectHeaders -XX:+UseShenandoahGC
98 * -XX:+UnlockDiagnosticVMOptions -XX:+VerifyDuringGC
99 * -XX:-ExplicitGCInvokesConcurrent
100 * -XX:ShenandoahGCHeuristics=aggressive
101 * -Xmx512m
102 * -XX:+UnlockExperimentalVMOptions -XX:ShenandoahRegionSize=256K
103 * gc.stress.ihash.TestHumongousHash
104 */
105
106 import java.util.ArrayList;
107 import java.util.Arrays;
108 import java.util.List;
109
110 public class TestHumongousHash {
111 public static void main(String[] args) {
112 // For G1, 50% of region size. For Shenandoah, 100%. We want to stress objects over the
113 // threshold, but also particularly objects near a region boundary (hash-code expansion)
114 // could see an object expand from below threshold to above threshold, or from fitting in
115 // N regions to requiring N+1 regions.
116 int humongousThreshold = 512 * 1024;
117
118 for (int i = 1; i < 10; i++) {
119 test(humongousThreshold * i);
120 }
121 }
122
123 static void test(int objectSize) {
124 List<byte[]> largeObjects = new ArrayList<>();
125 List<Integer> hashes = new ArrayList<>();
126
127 int numObjects = 0;
128 try {
129 while (true) {
130 // Stress various sizes near the threshold, below and above.
131 byte[] largeObject = new byte[objectSize + numObjects - 32];
132 Arrays.fill(largeObject, (byte) numObjects);
133 largeObjects.add(largeObject);
134 hashes.add(System.identityHashCode(largeObject));
135 numObjects++;
136 }
137 } catch (OutOfMemoryError e) {
138 // That's enough.
139 }
140
141 // Fragment so that GC can compact.
142 for (int i = 0; i < numObjects; i++) {
143 if (i % 2 == 0) {
144 largeObjects.set(i, null);
145 }
146 }
147
148 // Trigger compaction. System.gc() doesn't trigger it in all cases (e.g. G1), so we fill up
149 // the heap to trigger OOM, too.
150 System.gc();
151 ArrayList<byte[]> boom = new ArrayList<>();
152 try {
153 while (true) {
154 boom.add(new byte[100_000_000]);
155 }
156 } catch (OutOfMemoryError e) {
157 boom = null;
158 }
159
160 // Check for corruption in hash-code, length or data.
161 boolean fail = false;
162 for (int i = 0; i < numObjects; i++) {
163 if (i % 2 == 0) {
164 continue;
165 }
166 byte[] largeObject = largeObjects.get(i);
167 if (System.identityHashCode(largeObject) != hashes.get(i)) {
168 System.out.println("hash mismatch at " + i);
169 fail = true;
170 }
171 if (largeObject.length != objectSize - 32 + i) {
172 System.out.println("length corruption at " + i);
173 fail = true;
174 }
175 for (int x = 0; x < largeObject.length; x++) {
176 if (largeObject[x] != (byte) i) {
177 System.out.println("corruption at [" + i + "][" + x + "]");
178 fail = true;
179 }
180 }
181 }
182 if (fail) {
183 throw new RuntimeException("Identity hash-code, length or data corruption detected.");
184 }
185 }
186 }