Thu, 20 Mar 2014 16:31:47 +0100
8037510: CMM Testing: Min/MaxHeapFreeRatio flags should be manageable through the API
Summary: Added tests for Min/MaxHeapFreeRatio flags
Reviewed-by: jwilhelm, tschatzl
Contributed-by: andrey.x.zakharov@oracle.com
tschatzl@5701 | 1 | /* |
tschatzl@5701 | 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
tschatzl@5701 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
tschatzl@5701 | 4 | * |
tschatzl@5701 | 5 | * This code is free software; you can redistribute it and/or modify it |
tschatzl@5701 | 6 | * under the terms of the GNU General Public License version 2 only, as |
tschatzl@5701 | 7 | * published by the Free Software Foundation. |
tschatzl@5701 | 8 | * |
tschatzl@5701 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
tschatzl@5701 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
tschatzl@5701 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
tschatzl@5701 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
tschatzl@5701 | 13 | * accompanied this code). |
tschatzl@5701 | 14 | * |
tschatzl@5701 | 15 | * You should have received a copy of the GNU General Public License version |
tschatzl@5701 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
tschatzl@5701 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
tschatzl@5701 | 18 | * |
tschatzl@5701 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
tschatzl@5701 | 20 | * or visit www.oracle.com if you need additional information or have any |
tschatzl@5701 | 21 | * questions. |
tschatzl@5701 | 22 | */ |
tschatzl@5701 | 23 | |
tschatzl@5701 | 24 | import sun.management.ManagementFactoryHelper; |
tschatzl@5701 | 25 | import com.sun.management.HotSpotDiagnosticMXBean; |
tschatzl@5701 | 26 | import com.sun.management.VMOption; |
tschatzl@5701 | 27 | |
tschatzl@5701 | 28 | import java.util.regex.Matcher; |
tschatzl@5701 | 29 | import java.util.regex.Pattern; |
tschatzl@5701 | 30 | import java.util.ArrayList; |
tschatzl@5701 | 31 | import java.util.Arrays; |
tschatzl@5701 | 32 | |
tschatzl@5701 | 33 | import com.oracle.java.testlibrary.*; |
tschatzl@5701 | 34 | import sun.hotspot.WhiteBox; |
tschatzl@5701 | 35 | |
tschatzl@5701 | 36 | class DetermineMaxHeapForCompressedOops { |
tschatzl@5701 | 37 | public static void main(String[] args) throws Exception { |
tschatzl@5701 | 38 | WhiteBox wb = WhiteBox.getWhiteBox(); |
tschatzl@5701 | 39 | System.out.print(wb.getCompressedOopsMaxHeapSize()); |
tschatzl@5701 | 40 | } |
tschatzl@5701 | 41 | } |
tschatzl@5701 | 42 | |
tschatzl@5701 | 43 | class TestUseCompressedOopsErgoTools { |
tschatzl@5701 | 44 | |
tschatzl@5717 | 45 | private static long getCompressedClassSpaceSize() { |
tschatzl@5701 | 46 | HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); |
tschatzl@5701 | 47 | |
tschatzl@5717 | 48 | VMOption option = diagnostic.getVMOption("CompressedClassSpaceSize"); |
tschatzl@5701 | 49 | return Long.parseLong(option.getValue()); |
tschatzl@5701 | 50 | } |
tschatzl@5701 | 51 | |
tschatzl@5701 | 52 | |
tschatzl@5701 | 53 | public static long getMaxHeapForCompressedOops(String[] vmargs) throws Exception { |
tschatzl@5701 | 54 | OutputAnalyzer output = runWhiteBoxTest(vmargs, DetermineMaxHeapForCompressedOops.class.getName(), new String[] {}, false); |
tschatzl@5701 | 55 | return Long.parseLong(output.getStdout()); |
tschatzl@5701 | 56 | } |
tschatzl@5701 | 57 | |
tschatzl@5701 | 58 | public static boolean is64bitVM() { |
tschatzl@5701 | 59 | String val = System.getProperty("sun.arch.data.model"); |
tschatzl@5701 | 60 | if (val == null) { |
tschatzl@5701 | 61 | throw new RuntimeException("Could not read sun.arch.data.model"); |
tschatzl@5701 | 62 | } |
tschatzl@5701 | 63 | if (val.equals("64")) { |
tschatzl@5701 | 64 | return true; |
tschatzl@5701 | 65 | } else if (val.equals("32")) { |
tschatzl@5701 | 66 | return false; |
tschatzl@5701 | 67 | } |
tschatzl@5701 | 68 | throw new RuntimeException("Unexpected value " + val + " of sun.arch.data.model"); |
tschatzl@5701 | 69 | } |
tschatzl@5701 | 70 | |
tschatzl@5701 | 71 | /** |
tschatzl@5701 | 72 | * Executes a new VM process with the given class and parameters. |
tschatzl@5701 | 73 | * @param vmargs Arguments to the VM to run |
tschatzl@5701 | 74 | * @param classname Name of the class to run |
tschatzl@5701 | 75 | * @param arguments Arguments to the class |
tschatzl@5701 | 76 | * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string |
tschatzl@5701 | 77 | * @return The OutputAnalyzer with the results for the invocation. |
tschatzl@5701 | 78 | */ |
tschatzl@5701 | 79 | public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception { |
tschatzl@5701 | 80 | ArrayList<String> finalargs = new ArrayList<String>(); |
tschatzl@5701 | 81 | |
tschatzl@5701 | 82 | String[] whiteboxOpts = new String[] { |
tschatzl@5701 | 83 | "-Xbootclasspath/a:.", |
tschatzl@5701 | 84 | "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", |
tschatzl@5701 | 85 | "-cp", System.getProperty("java.class.path"), |
tschatzl@5701 | 86 | }; |
tschatzl@5701 | 87 | |
tschatzl@5701 | 88 | if (useTestDotJavaDotOpts) { |
tschatzl@5701 | 89 | // System.getProperty("test.java.opts") is '' if no options is set, |
tschatzl@5701 | 90 | // we need to skip such a result |
tschatzl@5701 | 91 | String[] externalVMOpts = new String[0]; |
tschatzl@5701 | 92 | if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { |
tschatzl@5701 | 93 | externalVMOpts = System.getProperty("test.java.opts").split(" "); |
tschatzl@5701 | 94 | } |
tschatzl@5701 | 95 | finalargs.addAll(Arrays.asList(externalVMOpts)); |
tschatzl@5701 | 96 | } |
tschatzl@5701 | 97 | |
tschatzl@5701 | 98 | finalargs.addAll(Arrays.asList(vmargs)); |
tschatzl@5701 | 99 | finalargs.addAll(Arrays.asList(whiteboxOpts)); |
tschatzl@5701 | 100 | finalargs.add(classname); |
tschatzl@5701 | 101 | finalargs.addAll(Arrays.asList(arguments)); |
tschatzl@5701 | 102 | |
tschatzl@5701 | 103 | ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); |
tschatzl@5701 | 104 | OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
tschatzl@5701 | 105 | output.shouldHaveExitValue(0); |
tschatzl@5701 | 106 | return output; |
tschatzl@5701 | 107 | } |
tschatzl@5701 | 108 | |
tschatzl@5701 | 109 | private static String[] join(String[] part1, String part2) { |
tschatzl@5701 | 110 | ArrayList<String> result = new ArrayList<String>(); |
tschatzl@5701 | 111 | result.addAll(Arrays.asList(part1)); |
tschatzl@5701 | 112 | result.add(part2); |
tschatzl@5701 | 113 | return result.toArray(new String[0]); |
tschatzl@5701 | 114 | } |
tschatzl@5701 | 115 | |
tschatzl@5701 | 116 | public static void checkCompressedOopsErgo(String[] gcflags) throws Exception { |
tschatzl@5701 | 117 | long maxHeapForCompressedOops = getMaxHeapForCompressedOops(gcflags); |
tschatzl@5701 | 118 | |
tschatzl@5701 | 119 | checkUseCompressedOops(gcflags, maxHeapForCompressedOops, true); |
tschatzl@5701 | 120 | checkUseCompressedOops(gcflags, maxHeapForCompressedOops - 1, true); |
tschatzl@5701 | 121 | checkUseCompressedOops(gcflags, maxHeapForCompressedOops + 1, false); |
tschatzl@5701 | 122 | |
tschatzl@5701 | 123 | // the use of HeapBaseMinAddress should not change the outcome |
tschatzl@5701 | 124 | checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops, true); |
tschatzl@5701 | 125 | checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops - 1, true); |
tschatzl@5701 | 126 | checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops + 1, false); |
tschatzl@5701 | 127 | |
tschatzl@5701 | 128 | // use a different object alignment |
tschatzl@5701 | 129 | maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16")); |
tschatzl@5701 | 130 | |
tschatzl@5701 | 131 | checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops, true); |
tschatzl@5701 | 132 | checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops - 1, true); |
tschatzl@5701 | 133 | checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops + 1, false); |
tschatzl@5701 | 134 | |
tschatzl@5717 | 135 | // use a different CompressedClassSpaceSize |
tschatzl@5717 | 136 | String compressedClassSpaceSizeArg = "-XX:CompressedClassSpaceSize=" + 2 * getCompressedClassSpaceSize(); |
tschatzl@5717 | 137 | maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, compressedClassSpaceSizeArg)); |
tschatzl@5701 | 138 | |
tschatzl@5717 | 139 | checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops, true); |
tschatzl@5717 | 140 | checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops - 1, true); |
tschatzl@5717 | 141 | checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops + 1, false); |
tschatzl@5701 | 142 | } |
tschatzl@5701 | 143 | |
tschatzl@5701 | 144 | private static void checkUseCompressedOops(String[] args, long heapsize, boolean expectUseCompressedOops) throws Exception { |
tschatzl@5701 | 145 | ArrayList<String> finalargs = new ArrayList<String>(); |
tschatzl@5701 | 146 | finalargs.addAll(Arrays.asList(args)); |
tschatzl@5701 | 147 | finalargs.add("-Xmx" + heapsize); |
tschatzl@5701 | 148 | finalargs.add("-XX:+PrintFlagsFinal"); |
tschatzl@5701 | 149 | finalargs.add("-version"); |
tschatzl@5701 | 150 | |
tschatzl@5701 | 151 | String output = expectValid(finalargs.toArray(new String[0])); |
tschatzl@5701 | 152 | |
tschatzl@5701 | 153 | boolean actualUseCompressedOops = getFlagBoolValue(" UseCompressedOops", output); |
tschatzl@5701 | 154 | |
tschatzl@5717 | 155 | Asserts.assertEQ(expectUseCompressedOops, actualUseCompressedOops); |
tschatzl@5701 | 156 | } |
tschatzl@5701 | 157 | |
tschatzl@5701 | 158 | private static boolean getFlagBoolValue(String flag, String where) { |
tschatzl@5701 | 159 | Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where); |
tschatzl@5701 | 160 | if (!m.find()) { |
tschatzl@5701 | 161 | throw new RuntimeException("Could not find value for flag " + flag + " in output string"); |
tschatzl@5701 | 162 | } |
tschatzl@5717 | 163 | return m.group(1).equals("true"); |
tschatzl@5701 | 164 | } |
tschatzl@5701 | 165 | |
tschatzl@5701 | 166 | private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { |
tschatzl@5701 | 167 | ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags); |
tschatzl@5701 | 168 | OutputAnalyzer output = new OutputAnalyzer(pb.start()); |
tschatzl@5701 | 169 | output.shouldHaveExitValue(errorcode); |
tschatzl@5701 | 170 | return output.getStdout(); |
tschatzl@5701 | 171 | } |
tschatzl@5701 | 172 | |
tschatzl@5701 | 173 | private static String expectValid(String[] flags) throws Exception { |
tschatzl@5701 | 174 | return expect(flags, false, false, 0); |
tschatzl@5701 | 175 | } |
tschatzl@5701 | 176 | } |
tschatzl@5701 | 177 |