1 /*
2  * Copyright (c) 2019, 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 gc.arguments;
25 
26 /*
27  * @test TestMaxRAMFlags
28  * @key gc
29  * @bug 8222252
30  * @summary Verify correct MaxHeapSize and UseCompressedOops when MaxRAM and MaxRAMPercentage
31  * are specified.
32  * @library /test/lib
33  * @library /
34  * @requires vm.bits == "64"
35  * @modules java.base/jdk.internal.misc
36  *          java.management
37  * @build sun.hotspot.WhiteBox
38  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
39  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
40  * @run main gc.arguments.TestMaxRAMFlags
41  * @author bob.vandette@oracle.com
42  */
43 
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46 
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 
50 import jdk.test.lib.process.OutputAnalyzer;
51 import jdk.test.lib.process.ProcessTools;
52 
53 public class TestMaxRAMFlags {
54 
checkMaxRAMSize(long maxram, int maxrampercent, boolean forcecoop, long expectheap, boolean expectcoop)55   private static void checkMaxRAMSize(long maxram, int maxrampercent, boolean forcecoop, long expectheap, boolean expectcoop) throws Exception {
56 
57     ArrayList<String> args = new ArrayList<String>();
58     args.add("-XX:MaxRAM=" + maxram);
59     args.add("-XX:MaxRAMPercentage=" + maxrampercent);
60     if (forcecoop) {
61       args.add("-XX:+UseCompressedOops");
62     }
63 
64     args.add("-XX:+PrintFlagsFinal");
65     args.add("-version");
66 
67     ProcessBuilder pb = GCArguments.createJavaProcessBuilder(args.toArray(new String[0]));
68     OutputAnalyzer output = new OutputAnalyzer(pb.start());
69     output.shouldHaveExitValue(0);
70     String stdout = output.getStdout();
71 
72     long actualheap = new Long(getFlagValue("MaxHeapSize", stdout)).longValue();
73     if (actualheap != expectheap) {
74       throw new RuntimeException("MaxHeapSize value set to " + actualheap +
75         ", expected " + expectheap + " when running with the following flags: " + Arrays.asList(args).toString());
76     }
77 
78     boolean actualcoop = getFlagBoolValue("UseCompressedOops", stdout);
79     if (actualcoop != expectcoop) {
80       throw new RuntimeException("UseCompressedOops set to " + actualcoop +
81         ", expected " + expectcoop + " when running with the following flags: " + Arrays.asList(args).toString());
82     }
83   }
84 
getHeapBaseMinAddress()85   private static long getHeapBaseMinAddress() throws Exception {
86     ArrayList<String> args = new ArrayList<String>();
87     args.add("-XX:+PrintFlagsFinal");
88     args.add("-version");
89 
90     ProcessBuilder pb = GCArguments.createJavaProcessBuilder(args.toArray(new String[0]));
91     OutputAnalyzer output = new OutputAnalyzer(pb.start());
92     output.shouldHaveExitValue(0);
93     String stdout = output.getStdout();
94     return (new Long(getFlagValue("HeapBaseMinAddress", stdout)).longValue());
95   }
96 
getFlagValue(String flag, String where)97   private static String getFlagValue(String flag, String where) {
98     Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
99     if (!m.find()) {
100       throw new RuntimeException("Could not find value for flag " + flag + " in output string");
101     }
102     String match = m.group();
103     return match.substring(match.lastIndexOf(" ") + 1, match.length());
104   }
105 
getFlagBoolValue(String flag, String where)106   private static boolean getFlagBoolValue(String flag, String where) {
107     Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
108     if (!m.find()) {
109       throw new RuntimeException("Could not find value for flag " + flag + " in output string");
110     }
111     return m.group(1).equals("true");
112   }
113 
main(String args[])114   public static void main(String args[]) throws Exception {
115     // Tests
116     // 1. Verify that MaxRAMPercentage overrides UseCompressedOops Ergo
117     // 2. Verify that UseCompressedOops forces compressed oops limit even
118     //    when other flags are specified.
119 
120     long oneG = 1L * 1024L * 1024L * 1024L;
121 
122     // Hotspot startup logic reduces MaxHeapForCompressedOops by HeapBaseMinAddress
123     // in order to get zero based compressed oops offsets.
124     long heapbaseminaddr = getHeapBaseMinAddress();
125     long maxcoopheap = TestUseCompressedOopsErgoTools.getMaxHeapForCompressedOops(new String [0]) - heapbaseminaddr;
126 
127     // Args: MaxRAM , MaxRAMPercentage, forcecoop, expect heap, expect coop
128     checkMaxRAMSize(maxcoopheap - oneG, 100, false, maxcoopheap - oneG, true);
129     checkMaxRAMSize(maxcoopheap + oneG, 100, false, maxcoopheap + oneG, false);
130     checkMaxRAMSize(maxcoopheap + oneG, 100, true, maxcoopheap, true);
131   }
132 }
133