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.parallel;
25
26 import java.util.Random;
27
28 /*
29 * @test TestHashedObjectCopy
30 * @bug 8379910
31 * @summary Parallel GC scavenge could read past the end of a hashed object
32 * when copying it to survivor/old space with compact object headers.
33 * If a hashed-but-not-expanded object sits at the very end of eden,
34 * the extra word read by copy_unmarked_to_survivor_space crosses into
35 * unmapped memory, causing a crash.
36 * @requires vm.gc.Parallel
37 * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders
38 * -XX:+UseParallelGC -Xmx128m -Xms128m -Xmn1m
39 * gc.parallel.TestHashedObjectCopy
40 */
41 public class TestHashedObjectCopy {
42
43 // Stress a variety of layouts.
44 static class S1 { byte a; }
45 static class S2 { byte a, b; }
46 static class S3 { byte a, b, c; }
47 static class S4 { byte a, b, c, d; }
48 static class S5 { byte a, b, c, d, e; }
49 static class S6 { byte a, b, c, d, e, f; }
50 static class S7 { byte a, b, c, d, e, f, g; }
51 static class S8 { byte a, b, c, d, e, f, g, h; }
52
53 static volatile int sink;
54
55 public static void main(String[] args) {
56 // Churn through different-sized objects. Keep some alive,
57 // because we're testing copy-to-survivor behaviour.
58 Random rng = new Random(42);
59 Object[] retained = new Object[10_000];
60 for (int cycle = 0; cycle < 1_000; cycle++) {
61 for (int i = 0; i < retained.length; i++) {
62 Object obj = switch (rng.nextInt(8)) {
63 case 0 -> new S1();
64 case 1 -> new S2();
65 case 2 -> new S3();
66 case 3 -> new S4();
67 case 4 -> new S5();
68 case 5 -> new S6();
69 case 6 -> new S7();
70 default -> new S8();
71 };
72 // Trigger expansion on copy.
73 sink = System.identityHashCode(obj);
74 retained[i] = obj;
75 }
76 }
77 }
78 }