TestUseCompressedOopsErgoTools.java revision 8359:ed6389f70257
1/*
2* Copyright (c) 2013, 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
24import com.sun.management.HotSpotDiagnosticMXBean;
25import com.sun.management.VMOption;
26
27import java.util.regex.Matcher;
28import java.util.regex.Pattern;
29import java.util.ArrayList;
30import java.util.Arrays;
31
32import jdk.test.lib.*;
33import java.lang.management.ManagementFactory;
34import sun.hotspot.WhiteBox;
35
36class DetermineMaxHeapForCompressedOops {
37  public static void main(String[] args) throws Exception {
38    WhiteBox wb = WhiteBox.getWhiteBox();
39    System.out.print(wb.getCompressedOopsMaxHeapSize());
40  }
41}
42
43class TestUseCompressedOopsErgoTools {
44
45  private static long getCompressedClassSpaceSize() {
46    HotSpotDiagnosticMXBean diagnostic =
47        ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
48
49    VMOption option = diagnostic.getVMOption("CompressedClassSpaceSize");
50    return Long.parseLong(option.getValue());
51  }
52
53
54  public static long getMaxHeapForCompressedOops(String[] vmargs) throws Exception {
55    OutputAnalyzer output = runWhiteBoxTest(vmargs, DetermineMaxHeapForCompressedOops.class.getName(), new String[] {}, false);
56    return Long.parseLong(output.getStdout());
57  }
58
59  public static boolean is64bitVM() {
60    String val = System.getProperty("sun.arch.data.model");
61    if (val == null) {
62      throw new RuntimeException("Could not read sun.arch.data.model");
63    }
64    if (val.equals("64")) {
65      return true;
66    } else if (val.equals("32")) {
67      return false;
68    }
69    throw new RuntimeException("Unexpected value " + val + " of sun.arch.data.model");
70  }
71
72  /**
73   * Executes a new VM process with the given class and parameters.
74   * @param vmargs Arguments to the VM to run
75   * @param classname Name of the class to run
76   * @param arguments Arguments to the class
77   * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
78   * @return The OutputAnalyzer with the results for the invocation.
79   */
80  public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
81    ArrayList<String> finalargs = new ArrayList<String>();
82
83    String[] whiteboxOpts = new String[] {
84      "-Xbootclasspath/a:.",
85      "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
86      "-cp", System.getProperty("java.class.path"),
87    };
88
89    if (useTestDotJavaDotOpts) {
90      // System.getProperty("test.java.opts") is '' if no options is set,
91      // we need to skip such a result
92      String[] externalVMOpts = new String[0];
93      if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
94        externalVMOpts = System.getProperty("test.java.opts").split(" ");
95      }
96      finalargs.addAll(Arrays.asList(externalVMOpts));
97    }
98
99    finalargs.addAll(Arrays.asList(vmargs));
100    finalargs.addAll(Arrays.asList(whiteboxOpts));
101    finalargs.add(classname);
102    finalargs.addAll(Arrays.asList(arguments));
103
104    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
105    OutputAnalyzer output = new OutputAnalyzer(pb.start());
106    output.shouldHaveExitValue(0);
107    return output;
108  }
109
110  private static String[] join(String[] part1, String part2) {
111    ArrayList<String> result = new ArrayList<String>();
112    result.addAll(Arrays.asList(part1));
113    result.add(part2);
114    return result.toArray(new String[0]);
115  }
116
117  public static void checkCompressedOopsErgo(String[] gcflags) throws Exception {
118    long maxHeapForCompressedOops = getMaxHeapForCompressedOops(gcflags);
119
120    checkUseCompressedOops(gcflags, maxHeapForCompressedOops, true);
121    checkUseCompressedOops(gcflags, maxHeapForCompressedOops - 1, true);
122    checkUseCompressedOops(gcflags, maxHeapForCompressedOops + 1, false);
123
124    // the use of HeapBaseMinAddress should not change the outcome
125    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops, true);
126    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops - 1, true);
127    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops + 1, false);
128
129    // use a different object alignment
130    maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"));
131
132    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops, true);
133    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops - 1, true);
134    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops + 1, false);
135
136    // use a different CompressedClassSpaceSize
137    String compressedClassSpaceSizeArg = "-XX:CompressedClassSpaceSize=" + 2 * getCompressedClassSpaceSize();
138    maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, compressedClassSpaceSizeArg));
139
140    checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops, true);
141    checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops - 1, true);
142    checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops + 1, false);
143  }
144
145  private static void checkUseCompressedOops(String[] args, long heapsize, boolean expectUseCompressedOops) throws Exception {
146     ArrayList<String> finalargs = new ArrayList<String>();
147     finalargs.addAll(Arrays.asList(args));
148     finalargs.add("-Xmx" + heapsize);
149     finalargs.add("-XX:+PrintFlagsFinal");
150     finalargs.add("-version");
151
152     String output = expectValid(finalargs.toArray(new String[0]));
153
154     boolean actualUseCompressedOops = getFlagBoolValue(" UseCompressedOops", output);
155
156     Asserts.assertEQ(expectUseCompressedOops, actualUseCompressedOops);
157  }
158
159  private static boolean getFlagBoolValue(String flag, String where) {
160    Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
161    if (!m.find()) {
162      throw new RuntimeException("Could not find value for flag " + flag + " in output string");
163    }
164    return m.group(1).equals("true");
165  }
166
167  private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception {
168    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
169    OutputAnalyzer output = new OutputAnalyzer(pb.start());
170    output.shouldHaveExitValue(errorcode);
171    return output.getStdout();
172  }
173
174  private static String expectValid(String[] flags) throws Exception {
175    return expect(flags, false, false, 0);
176  }
177}
178