Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java
32285 views
1
/*
2
* Copyright (c) 2013, Oracle and/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
import java.util.regex.Matcher;
25
import java.util.regex.Pattern;
26
import java.util.ArrayList;
27
import java.util.Arrays;
28
29
import com.oracle.java.testlibrary.*;
30
import sun.hotspot.WhiteBox;
31
32
class ErgoArgsPrinter {
33
public static void main(String[] args) throws Exception {
34
WhiteBox wb = WhiteBox.getWhiteBox();
35
wb.printHeapSizes();
36
}
37
}
38
39
final class MinInitialMaxValues {
40
public long minHeapSize;
41
public long initialHeapSize;
42
public long maxHeapSize;
43
44
public long spaceAlignment;
45
public long heapAlignment;
46
}
47
48
class TestMaxHeapSizeTools {
49
50
public static void checkMinInitialMaxHeapFlags(String gcflag) throws Exception {
51
checkInvalidMinInitialHeapCombinations(gcflag);
52
checkValidMinInitialHeapCombinations(gcflag);
53
checkInvalidInitialMaxHeapCombinations(gcflag);
54
checkValidInitialMaxHeapCombinations(gcflag);
55
}
56
57
public static void checkMinInitialErgonomics(String gcflag) throws Exception {
58
// heap sizing ergonomics use the value NewSize + OldSize as default values
59
// for ergonomics calculation. Retrieve these values.
60
long[] values = new long[2];
61
getNewOldSize(gcflag, values);
62
63
// we check cases with values smaller and larger than this default value.
64
long newPlusOldSize = values[0] + values[1];
65
long smallValue = newPlusOldSize / 2;
66
long largeValue = newPlusOldSize * 2;
67
long maxHeapSize = largeValue + (2 * 1024 * 1024);
68
69
// -Xms is not set
70
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1);
71
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
72
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
73
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1);
74
75
// -Xms is set to zero
76
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1);
77
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue);
78
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue);
79
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1);
80
81
// -Xms is set to small value
82
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1);
83
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue);
84
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue);
85
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1);
86
87
// -Xms is set to large value
88
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue);
89
checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1);
90
}
91
92
private static long align_up(long value, long alignment) {
93
long alignmentMinusOne = alignment - 1;
94
return (value + alignmentMinusOne) & ~alignmentMinusOne;
95
}
96
97
private static void getNewOldSize(String gcflag, long[] values) throws Exception {
98
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(gcflag,
99
"-XX:+PrintFlagsFinal", "-version");
100
OutputAnalyzer output = new OutputAnalyzer(pb.start());
101
output.shouldHaveExitValue(0);
102
103
String stdout = output.getStdout();
104
values[0] = getFlagValue(" NewSize", stdout);
105
values[1] = getFlagValue(" OldSize", stdout);
106
}
107
108
public static void checkGenMaxHeapErgo(String gcflag) throws Exception {
109
TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 3);
110
TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 4);
111
TestMaxHeapSizeTools.checkGenMaxHeapSize(gcflag, 5);
112
}
113
114
private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
115
expectError(new String[] { gcflag, "-Xms8M", "-XX:InitialHeapSize=4M", "-version" });
116
}
117
118
private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
119
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms4M", "-version" });
120
expectValid(new String[] { gcflag, "-Xms4M", "-XX:InitialHeapSize=8M", "-version" });
121
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-Xms8M", "-version" });
122
// the following is not an error as -Xms sets both minimal and initial heap size
123
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-Xms8M", "-version" });
124
}
125
126
private static void checkInvalidInitialMaxHeapCombinations(String gcflag) throws Exception {
127
expectError(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=8M", "-version" });
128
expectError(new String[] { gcflag, "-XX:InitialHeapSize=8M", "-XX:MaxHeapSize=4M", "-version" });
129
}
130
131
private static void checkValidInitialMaxHeapCombinations(String gcflag) throws Exception {
132
expectValid(new String[] { gcflag, "-XX:InitialHeapSize=4M", "-XX:MaxHeapSize=8M", "-version" });
133
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=8M", "-XX:InitialHeapSize=4M", "-version" });
134
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=4M", "-version" });
135
// a value of "0" for initial heap size means auto-detect
136
expectValid(new String[] { gcflag, "-XX:MaxHeapSize=4M", "-XX:InitialHeapSize=0M", "-version" });
137
}
138
139
private static long valueAfter(String source, String match) {
140
int start = source.indexOf(match) + match.length();
141
String tail = source.substring(start).split(" ")[0];
142
return Long.parseLong(tail);
143
}
144
145
/**
146
* Executes a new VM process with the given class and parameters.
147
* @param vmargs Arguments to the VM to run
148
* @param classname Name of the class to run
149
* @param arguments Arguments to the class
150
* @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
151
* @return The OutputAnalyzer with the results for the invocation.
152
*/
153
public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
154
ArrayList<String> finalargs = new ArrayList<String>();
155
156
String[] whiteboxOpts = new String[] {
157
"-Xbootclasspath/a:.",
158
"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
159
"-cp", System.getProperty("java.class.path"),
160
};
161
162
if (useTestDotJavaDotOpts) {
163
// System.getProperty("test.java.opts") is '' if no options is set,
164
// we need to skip such a result
165
String[] externalVMOpts = new String[0];
166
if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
167
externalVMOpts = System.getProperty("test.java.opts").split(" ");
168
}
169
finalargs.addAll(Arrays.asList(externalVMOpts));
170
}
171
172
finalargs.addAll(Arrays.asList(vmargs));
173
finalargs.addAll(Arrays.asList(whiteboxOpts));
174
finalargs.add(classname);
175
finalargs.addAll(Arrays.asList(arguments));
176
177
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
178
OutputAnalyzer output = new OutputAnalyzer(pb.start());
179
output.shouldHaveExitValue(0);
180
181
return output;
182
}
183
184
private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) throws Exception {
185
OutputAnalyzer output = runWhiteBoxTest(args, ErgoArgsPrinter.class.getName(), new String[] {}, false);
186
187
// the output we watch for has the following format:
188
//
189
// "Minimum heap X Initial heap Y Maximum heap Z Min alignment A Max Alignment B"
190
//
191
// where A, B, X, Y and Z are sizes in bytes.
192
// Unfortunately there is no other way to retrieve the minimum heap size and
193
// the alignments.
194
195
Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Space alignment \\d+ Heap alignment \\d+").
196
matcher(output.getStdout());
197
if (!m.find()) {
198
throw new RuntimeException("Could not find heap size string.");
199
}
200
201
String match = m.group();
202
203
// actual values
204
val.minHeapSize = valueAfter(match, "Minimum heap ");
205
val.initialHeapSize = valueAfter(match, "Initial heap ");
206
val.maxHeapSize = valueAfter(match, "Maximum heap ");
207
val.spaceAlignment = valueAfter(match, "Space alignment ");
208
val.heapAlignment = valueAfter(match, "Heap alignment ");
209
}
210
211
/**
212
* Verify whether the VM automatically synchronizes minimum and initial heap size if only
213
* one is given for the GC specified.
214
*/
215
public static void checkErgonomics(String[] args, long[] newoldsize,
216
long expectedMin, long expectedInitial) throws Exception {
217
218
MinInitialMaxValues v = new MinInitialMaxValues();
219
getMinInitialMaxHeap(args, v);
220
221
if ((expectedMin != -1) && (align_up(expectedMin, v.heapAlignment) != v.minHeapSize)) {
222
throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize +
223
" differs from expected minimum heap size of " + expectedMin);
224
}
225
226
if ((expectedInitial != -1) && (align_up(expectedInitial, v.heapAlignment) != v.initialHeapSize)) {
227
throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize +
228
" differs from expected initial heap size of " + expectedInitial);
229
}
230
231
// always check the invariant min <= initial <= max heap size
232
if (!(v.minHeapSize <= v.initialHeapSize && v.initialHeapSize <= v.maxHeapSize)) {
233
throw new RuntimeException("Inconsistent min/initial/max heap sizes, they are " +
234
v.minHeapSize + "/" + v.initialHeapSize + "/" + v.maxHeapSize);
235
}
236
}
237
238
/**
239
* Verify whether the VM respects the given maximum heap size in MB for the
240
* GC specified.
241
* @param gcflag The garbage collector to test as command line flag. E.g. -XX:+UseG1GC
242
* @param maxHeapSize the maximum heap size to verify, in MB.
243
*/
244
public static void checkGenMaxHeapSize(String gcflag, long maxHeapsize) throws Exception {
245
final long K = 1024;
246
247
MinInitialMaxValues v = new MinInitialMaxValues();
248
getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v);
249
250
long expectedHeapSize = align_up(maxHeapsize * K * K, v.heapAlignment);
251
long actualHeapSize = v.maxHeapSize;
252
253
if (actualHeapSize > expectedHeapSize) {
254
throw new RuntimeException("Heap has " + actualHeapSize +
255
" bytes, expected to be less than " + expectedHeapSize);
256
}
257
}
258
259
private static long getFlagValue(String flag, String where) {
260
Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
261
if (!m.find()) {
262
throw new RuntimeException("Could not find value for flag " + flag + " in output string");
263
}
264
String match = m.group();
265
return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length()));
266
}
267
268
private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, String message) throws Exception {
269
if (contains) {
270
output.shouldContain(message);
271
} else {
272
output.shouldNotContain(message);
273
}
274
}
275
276
private static void expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception {
277
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
278
OutputAnalyzer output = new OutputAnalyzer(pb.start());
279
shouldContainOrNot(output, hasWarning, "Warning");
280
shouldContainOrNot(output, hasError, "Error");
281
output.shouldHaveExitValue(errorcode);
282
}
283
284
private static void expectError(String[] flags) throws Exception {
285
expect(flags, false, true, 1);
286
}
287
288
private static void expectValid(String[] flags) throws Exception {
289
expect(flags, false, false, 0);
290
}
291
}
292
293
294