1 /*
2 * Copyright (c) 2018, Red Hat, 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 /**
26 * @test id=large
27 * @summary Test allocation of large objects results in OOM, but will not crash the JVM
28 * @requires vm.gc.Shenandoah
29 * @library /test/lib
30 * @run driver TestAllocOutOfMemory large
31 */
32
33 /**
34 * @test id=heap
35 * @summary Test allocation of a heap-sized object results in OOM, but will not crash the JVM
36 * @requires vm.gc.Shenandoah
37 * @library /test/lib
38 * @run driver TestAllocOutOfMemory heap
39 */
40
41 /**
42 * @test id=small
43 * @summary Test allocation of small objects results in OOM, but will not crash the JVM
44 * @requires vm.gc.Shenandoah
45 * @library /test/lib
46 * @run driver TestAllocOutOfMemory small
47 */
48
49 import jdk.test.lib.process.OutputAnalyzer;
50 import jdk.test.lib.process.ProcessTools;
51
52 public class TestAllocOutOfMemory {
53
54 static volatile Object sink;
55
56 public static void work(int size, int count) throws Exception {
57 Object[] root = new Object[count];
58 sink = root;
59 for (int c = 0; c < count; c++) {
60 root[c] = new Object[size];
61 }
62 }
63
64 private static void allocate(String size, int multiplier) throws Exception {
65 switch (size) {
66 case "large":
67 work(1024 * 1024, 16 * multiplier);
68 break;
69 case "heap":
70 work(16 * 1024 * 1024, multiplier);
71 break;
72 case "small":
73 work(1, 16 * 1024 * 1024 * multiplier);
74 break;
75 default:
76 throw new IllegalArgumentException("Usage: test [large|small|heap]");
77 }
78 }
79
80 public static void main(String[] args) throws Exception {
81 if (args.length > 2) {
82 // Called from test, size is second argument, heap requested is third
83 String size = args[1];
84 long spec_heap = Integer.parseInt(args[2]);
85
86 // The actual heap we get may be larger than the one we asked for
87 // (particularly in the generational case)
88 final long actual_heap = Runtime.getRuntime().maxMemory();
89 int multiplier = 1;
90 if (actual_heap > spec_heap) {
91 // A suitable multiplier is used, so as to allocate an
92 // amount appropriate to the larger actual heap size than what
93 // was specified.
94 multiplier = (int)((actual_heap + spec_heap - 1)/spec_heap);
95 }
96
97 allocate(size, multiplier);
98 return;
99 }
100
101 // Called from jtreg, size is first argument
102 String size = args[0];
103 {
104 int heap = 16*1024*1024; // -Xmx16m
105 expectFailure("-Xmx16m",
106 "-XX:+UnlockExperimentalVMOptions",
107 "-XX:+UseShenandoahGC",
108 TestAllocOutOfMemory.class.getName(),
109 "test", size, Integer.toString(heap));
110
111 expectFailure("-Xmx16m",
112 "-XX:+UnlockExperimentalVMOptions",
113 "-XX:+UseShenandoahGC", "-XX:ShenandoahGCMode=generational",
114 TestAllocOutOfMemory.class.getName(),
115 "test", size, Integer.toString(heap));
116 }
117
118 {
119 int heap = 1*1024*1024*1024; // -Xmx1g
120 expectSuccess("-Xmx1g",
121 "-XX:+UnlockExperimentalVMOptions",
122 "-XX:+UseShenandoahGC",
123 TestAllocOutOfMemory.class.getName(),
124 "test", size, Integer.toString(heap));
125
126 expectSuccess("-Xmx1g",
127 "-XX:+UnlockExperimentalVMOptions",
128 "-XX:+UseShenandoahGC", "-XX:ShenandoahGCMode=generational",
129 TestAllocOutOfMemory.class.getName(),
130 "test", size, Integer.toString(heap));
131 }
132 }
133
134 private static void expectSuccess(String... args) throws Exception {
135 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args);
136 OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
137 analyzer.shouldHaveExitValue(0);
138 analyzer.shouldNotContain("java.lang.OutOfMemoryError: Java heap space");
139 }
140
141 private static void expectFailure(String... args) throws Exception {
142 ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args);
143 OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
144 analyzer.shouldHaveExitValue(1);
145 analyzer.shouldContain("java.lang.OutOfMemoryError: Java heap space");
146 }
147 }