1 /*
2 * Copyright (c) 2015, 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 package optionsvalidation;
25
26 import java.io.BufferedReader;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.Reader;
30 import java.math.BigDecimal;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.LinkedHashMap;
35 import java.util.Map;
36 import java.util.StringTokenizer;
37 import java.util.function.Predicate;
38 import jdk.test.lib.OutputAnalyzer;
39 import jdk.test.lib.Platform;
40 import jdk.test.lib.ProcessTools;
41
42 public class JVMOptionsUtils {
43
44 /* Java option which print options with ranges */
45 private static final String PRINT_FLAGS_RANGES = "-XX:+PrintFlagsRanges";
46
47 /* StringBuilder to accumulate failed message */
48 private static final StringBuilder finalFailedMessage = new StringBuilder();
49
50 /* Used to start the JVM with the same type as current */
51 static String VMType;
52
53 private static Map<String, JVMOption> optionsAsMap;
54
55 static {
56 if (Platform.isServer()) {
57 VMType = "-server";
58 } else if (Platform.isClient()) {
59 VMType = "-client";
60 } else if (Platform.isMinimal()) {
61 VMType = "-minimal";
62 } else if (Platform.isGraal()) {
63 VMType = "-graal";
64 } else {
65 VMType = null;
66 }
67 }
68
69 public static boolean fitsRange(String optionName, BigDecimal number) throws Exception {
70 JVMOption option;
71 String minRangeString = null;
72 String maxRangeString = null;
73 boolean fits = true;
74
75 if (optionsAsMap == null) {
76 optionsAsMap = getOptionsWithRangeAsMap();
77 }
78
79 option = optionsAsMap.get(optionName);
80 if (option != null) {
81 minRangeString = option.getMin();
82 if (minRangeString != null) {
83 fits = (number.compareTo(new BigDecimal(minRangeString)) >= 0);
84 }
85 maxRangeString = option.getMax();
86 if (maxRangeString != null) {
136 optionsAsMap = getOptionsWithRangeAsMap();
137 }
138
139 option = optionsAsMap.get(optionName);
140 if (option != null) {
141 maxRange = option.getMax();
142 }
143
144 return maxRange;
145 }
146
147 /**
148 * Add dependency for option depending on it's name. E.g. enable G1 GC for
149 * G1 options or add prepend options to not hit constraints.
150 *
151 * @param option option
152 */
153 private static void addNameDependency(JVMOption option) {
154 String name = option.getName();
155
156 if (name.startsWith("G1")) {
157 option.addPrepend("-XX:+UseG1GC");
158 }
159
160 if (name.startsWith("CMS")) {
161 option.addPrepend("-XX:+UseConcMarkSweepGC");
162 }
163
164 if (name.startsWith("NUMA")) {
165 option.addPrepend("-XX:+UseNUMA");
166 }
167
168 switch (name) {
169 case "MinHeapFreeRatio":
170 option.addPrepend("-XX:MaxHeapFreeRatio=100");
171 break;
172 case "MaxHeapFreeRatio":
173 option.addPrepend("-XX:MinHeapFreeRatio=0");
174 break;
175 case "MinMetaspaceFreeRatio":
176 option.addPrepend("-XX:MaxMetaspaceFreeRatio=100");
177 break;
178 case "MaxMetaspaceFreeRatio":
179 option.addPrepend("-XX:MinMetaspaceFreeRatio=0");
180 break;
181 case "CMSOldPLABMin":
182 option.addPrepend("-XX:CMSOldPLABMax=" + option.getMax());
183 break;
426 * to true.
427 * @param additionalArgs additional arguments to the Java process which ran
428 * with "-XX:+PrintFlagsRanges"
429 * @return map from option name to the JVMOption object
430 * @throws Exception if a new process can not be created or an error
431 * occurred while reading the data
432 */
433 public static Map<String, JVMOption> getOptionsAsMap(boolean withRanges, Predicate<String> acceptOrigin,
434 String... additionalArgs) throws Exception {
435 Map<String, JVMOption> result;
436 Process p;
437 List<String> runJava = new ArrayList<>();
438
439 if (additionalArgs.length > 0) {
440 runJava.addAll(Arrays.asList(additionalArgs));
441 }
442
443 if (VMType != null) {
444 runJava.add(VMType);
445 }
446 runJava.add(PRINT_FLAGS_RANGES);
447 runJava.add("-version");
448
449 p = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start();
450
451 result = getJVMOptions(new InputStreamReader(p.getInputStream()), withRanges, acceptOrigin);
452
453 p.waitFor();
454
455 return result;
456 }
457
458 /**
459 * Get JVM options as list. Can return options with defined ranges or
460 * options without range depending on "withRanges" argument. "acceptOrigin"
461 * predicate can be used to filter option origin.
462 *
463 * @param withRanges true if needed options with defined ranges inside JVM
464 * @param acceptOrigin predicate for option origins. Origins can be
465 * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
516 * with "-XX:+PrintFlagsRanges"
517 * @return Map from option name to the JVMOption object
518 * @throws Exception if a new process can not be created or an error
519 * occurred while reading the data
520 */
521 public static Map<String, JVMOption> getOptionsWithRangeAsMap(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
522 return getOptionsAsMap(true, acceptOrigin, additionalArgs);
523 }
524
525 /**
526 * Get JVM options with range as map
527 *
528 * @param additionalArgs additional arguments to the Java process which ran
529 * with "-XX:+PrintFlagsRanges"
530 * @return map from option name to the JVMOption object
531 * @throws Exception if a new process can not be created or an error
532 * occurred while reading the data
533 */
534 public static Map<String, JVMOption> getOptionsWithRangeAsMap(String... additionalArgs) throws Exception {
535 return getOptionsWithRangeAsMap(origin -> true, additionalArgs);
536 }
537
538 /* Simple method to test that java start-up. Used for testing options. */
539 public static void main(String[] args) {
540 System.out.print("Java start-up!");
541 }
542 }
|
1 /*
2 * Copyright (c) 2015, 2016, 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 package optionsvalidation;
25
26 import java.io.BufferedReader;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.Reader;
30 import java.lang.management.GarbageCollectorMXBean;
31 import java.lang.management.ManagementFactory;
32 import java.math.BigDecimal;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.List;
36 import java.util.LinkedHashMap;
37 import java.util.Map;
38 import java.util.StringTokenizer;
39 import java.util.function.Predicate;
40 import jdk.test.lib.OutputAnalyzer;
41 import jdk.test.lib.Platform;
42 import jdk.test.lib.ProcessTools;
43
44 public class JVMOptionsUtils {
45
46 /* Java option which print options with ranges */
47 private static final String PRINT_FLAGS_RANGES = "-XX:+PrintFlagsRanges";
48
49 /* StringBuilder to accumulate failed message */
50 private static final StringBuilder finalFailedMessage = new StringBuilder();
51
52 /* Used to start the JVM with the same type as current */
53 static String VMType;
54
55 /* Used to start the JVM with the same GC type as current */
56 static String GCType;
57
58 private static Map<String, JVMOption> optionsAsMap;
59
60 static {
61 if (Platform.isServer()) {
62 VMType = "-server";
63 } else if (Platform.isClient()) {
64 VMType = "-client";
65 } else if (Platform.isMinimal()) {
66 VMType = "-minimal";
67 } else if (Platform.isGraal()) {
68 VMType = "-graal";
69 } else {
70 VMType = null;
71 }
72
73 List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
74
75 GCType = null;
76
77 for (GarbageCollectorMXBean gcMxBean : gcMxBeans) {
78 switch (gcMxBean.getName()) {
79 case "ConcurrentMarkSweep":
80 GCType = "-XX:+UseConcMarkSweepGC";
81 break;
82 case "MarkSweepCompact":
83 GCType = "-XX:+UseSerialGC";
84 break;
85 case "PS Scavenge":
86 GCType = "-XX:+UseParallelGC";
87 break;
88 case "G1 Old Generation":
89 GCType = "-XX:+UseG1GC";
90 break;
91 }
92 }
93 }
94
95 public static boolean fitsRange(String optionName, BigDecimal number) throws Exception {
96 JVMOption option;
97 String minRangeString = null;
98 String maxRangeString = null;
99 boolean fits = true;
100
101 if (optionsAsMap == null) {
102 optionsAsMap = getOptionsWithRangeAsMap();
103 }
104
105 option = optionsAsMap.get(optionName);
106 if (option != null) {
107 minRangeString = option.getMin();
108 if (minRangeString != null) {
109 fits = (number.compareTo(new BigDecimal(minRangeString)) >= 0);
110 }
111 maxRangeString = option.getMax();
112 if (maxRangeString != null) {
162 optionsAsMap = getOptionsWithRangeAsMap();
163 }
164
165 option = optionsAsMap.get(optionName);
166 if (option != null) {
167 maxRange = option.getMax();
168 }
169
170 return maxRange;
171 }
172
173 /**
174 * Add dependency for option depending on it's name. E.g. enable G1 GC for
175 * G1 options or add prepend options to not hit constraints.
176 *
177 * @param option option
178 */
179 private static void addNameDependency(JVMOption option) {
180 String name = option.getName();
181
182 if (name.startsWith("NUMA")) {
183 option.addPrepend("-XX:+UseNUMA");
184 }
185
186 switch (name) {
187 case "MinHeapFreeRatio":
188 option.addPrepend("-XX:MaxHeapFreeRatio=100");
189 break;
190 case "MaxHeapFreeRatio":
191 option.addPrepend("-XX:MinHeapFreeRatio=0");
192 break;
193 case "MinMetaspaceFreeRatio":
194 option.addPrepend("-XX:MaxMetaspaceFreeRatio=100");
195 break;
196 case "MaxMetaspaceFreeRatio":
197 option.addPrepend("-XX:MinMetaspaceFreeRatio=0");
198 break;
199 case "CMSOldPLABMin":
200 option.addPrepend("-XX:CMSOldPLABMax=" + option.getMax());
201 break;
444 * to true.
445 * @param additionalArgs additional arguments to the Java process which ran
446 * with "-XX:+PrintFlagsRanges"
447 * @return map from option name to the JVMOption object
448 * @throws Exception if a new process can not be created or an error
449 * occurred while reading the data
450 */
451 public static Map<String, JVMOption> getOptionsAsMap(boolean withRanges, Predicate<String> acceptOrigin,
452 String... additionalArgs) throws Exception {
453 Map<String, JVMOption> result;
454 Process p;
455 List<String> runJava = new ArrayList<>();
456
457 if (additionalArgs.length > 0) {
458 runJava.addAll(Arrays.asList(additionalArgs));
459 }
460
461 if (VMType != null) {
462 runJava.add(VMType);
463 }
464
465 if (GCType != null) {
466 runJava.add(GCType);
467 }
468 runJava.add(PRINT_FLAGS_RANGES);
469 runJava.add("-version");
470
471 p = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start();
472
473 result = getJVMOptions(new InputStreamReader(p.getInputStream()), withRanges, acceptOrigin);
474
475 p.waitFor();
476
477 return result;
478 }
479
480 /**
481 * Get JVM options as list. Can return options with defined ranges or
482 * options without range depending on "withRanges" argument. "acceptOrigin"
483 * predicate can be used to filter option origin.
484 *
485 * @param withRanges true if needed options with defined ranges inside JVM
486 * @param acceptOrigin predicate for option origins. Origins can be
487 * "product", "diagnostic" etc. Accept option only if acceptOrigin evaluates
538 * with "-XX:+PrintFlagsRanges"
539 * @return Map from option name to the JVMOption object
540 * @throws Exception if a new process can not be created or an error
541 * occurred while reading the data
542 */
543 public static Map<String, JVMOption> getOptionsWithRangeAsMap(Predicate<String> acceptOrigin, String... additionalArgs) throws Exception {
544 return getOptionsAsMap(true, acceptOrigin, additionalArgs);
545 }
546
547 /**
548 * Get JVM options with range as map
549 *
550 * @param additionalArgs additional arguments to the Java process which ran
551 * with "-XX:+PrintFlagsRanges"
552 * @return map from option name to the JVMOption object
553 * @throws Exception if a new process can not be created or an error
554 * occurred while reading the data
555 */
556 public static Map<String, JVMOption> getOptionsWithRangeAsMap(String... additionalArgs) throws Exception {
557 return getOptionsWithRangeAsMap(origin -> true, additionalArgs);
558 }
559 }
|