TestNewSizeFlags.java revision 11833:1cbffa2beba6
1136644Sache/* 2136644Sache * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 321308Sache * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 421308Sache * 521308Sache * This code is free software; you can redistribute it and/or modify it 621308Sache * under the terms of the GNU General Public License version 2 only, as 721308Sache * published by the Free Software Foundation. 821308Sache * 958310Sache * This code is distributed in the hope that it will be useful, but WITHOUT 1021308Sache * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1121308Sache * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1221308Sache * version 2 for more details (a copy is included in the LICENSE file that 1321308Sache * accompanied this code). 1421308Sache * 1521308Sache * You should have received a copy of the GNU General Public License version 1621308Sache * 2 along with this work; if not, write to the Free Software Foundation, 1721308Sache * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1821308Sache * 1921308Sache * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2058310Sache * or visit www.oracle.com if you need additional information or have any 2121308Sache * questions. 2221308Sache */ 2321308Sache 2421308Sache/* 2547558Sache * @test TestNewSizeFlags 2647558Sache * @key gc 2747558Sache * @bug 8025166 2847558Sache * @summary Verify that young gen size conforms values specified by NewSize, MaxNewSize and Xmn options 29136644Sache * @library /test/lib 30136644Sache * @modules java.base/jdk.internal.misc 3147558Sache * java.management 3247558Sache * @build sun.hotspot.WhiteBox 3375406Sache * @run main ClassFileInstaller sun.hotspot.WhiteBox 3447558Sache * @run driver/timeout=240 TestNewSizeFlags 3547558Sache */ 3675406Sache 3747558Sacheimport java.io.IOException; 3847558Sacheimport java.lang.management.MemoryUsage; 3947558Sacheimport java.util.Arrays; 4047558Sacheimport java.util.Collections; 4147558Sacheimport java.util.LinkedList; 4247558Sacheimport jdk.test.lib.process.OutputAnalyzer; 4347558Sacheimport jdk.test.lib.process.ProcessTools; 4447558Sacheimport jdk.test.lib.Utils; 4521308Sacheimport sun.hotspot.WhiteBox; 4621308Sache 4721308Sachepublic class TestNewSizeFlags { 48136644Sache 4947558Sache public static final long M = 1024 * 1024; 5021308Sache 5121308Sache public static void main(String args[]) throws Exception { 52136644Sache LinkedList<String> options = new LinkedList<>( 53136644Sache Arrays.asList(Utils.getFilteredTestJavaOpts("(-Xm[nsx][^ ]+)|" 54136644Sache + "(-XX:(Max)?((New)|" 5521308Sache + "(Heap))((Size)|" 5621308Sache + "(Ratio))=[^ ]+)")) 5721308Sache ); 5821308Sache 5921308Sache // Test NewSize and MaxNewSize 6021308Sache testNewSizeFlags(20 * M, 10 * M, 30 * M, 40 * M, options, false); 6121308Sache testNewSizeFlags(10 * M, 20 * M, 30 * M, 80 * M, options, false); 6221308Sache testNewSizeFlags(-1, 20 * M, 30 * M, 40 * M, options, false); 6321308Sache testNewSizeFlags(10 * M, -1, 30 * M, 40 * M, options, false); 6421308Sache testNewSizeFlags(20 * M, 20 * M, 30 * M, 40 * M, options, false); 6521308Sache testNewSizeFlags(20 * M, 30 * M, 40 * M, 50 * M, options, false); 6621308Sache testNewSizeFlags(30 * M, 100 * M, 150 * M, 200 * M, options, false); 6721308Sache testNewSizeFlags(20 * M, 30 * M, 128 * M, 128 * M, options, false); 6821308Sache 6921308Sache // Test -Xmn 7021308Sache testXmnFlags(0, 30 * M, 40 * M, options, true); 71119610Sache testXmnFlags(20 * M, 30 * M, 40 * M, options, false); 7221308Sache testXmnFlags(50 * M, 70 * M, 100 * M, options, false); 7321308Sache } 74119610Sache 7521308Sache /** 7621308Sache * Verify that NewSize and MaxNewSize flags affect young gen size. 77119610Sache * 7821308Sache * @param newSize value of NewSize option, omitted if negative 7921308Sache * @param maxNewSize value of MaxNewSize option, omitted if negative 8021308Sache * @param heapSize value of HeapSize option 8121308Sache * @param maxHeapSize value of MaxHeapSize option 8221308Sache * @param options additional options for JVM 83119610Sache * @param failureExpected true if JVM should fail with passed heap size options 8421308Sache */ 85136644Sache public static void testNewSizeFlags(long newSize, long maxNewSize, 86136644Sache long heapSize, long maxHeapSize, 87136644Sache LinkedList<String> options, 88136644Sache boolean failureExpected) throws Exception { 8921308Sache long expectedNewSize = newSize; 9021308Sache long expectedMaxNewSize = (maxNewSize >= 0 ? Math.max(maxNewSize, newSize) : maxNewSize); 9121308Sache testVMOptions(newSize, maxNewSize, 92119610Sache heapSize, maxHeapSize, 9321308Sache expectedNewSize, expectedMaxNewSize, 94136644Sache options, failureExpected); 95136644Sache } 96136644Sache 97136644Sache /** 9821308Sache * Verify that -Xmn flag affect young gen size. 9921308Sache * 10021308Sache * @param mnValue value of -Xmn option 101119610Sache * @param heapSize value of HeapSize option 10221308Sache * @param maxHeapSize value of MaxHeapSize option 10321308Sache * @param options additional options for JVM 104119610Sache * @param failureExpected true if JVM should fail with passed heap size options 10521308Sache */ 10621308Sache public static void testXmnFlags(long mnValue, 107119610Sache long heapSize, long maxHeapSize, 10821308Sache LinkedList<String> options, 10921308Sache boolean failureExpected) throws Exception { 11021308Sache LinkedList<String> newOptions = new LinkedList<>(options); 11121308Sache newOptions.add("-Xmn" + mnValue); 112119610Sache testVMOptions(-1, -1, 11321308Sache heapSize, maxHeapSize, 11421308Sache mnValue, mnValue, 115119610Sache newOptions, failureExpected); 11621308Sache } 11721308Sache 11821308Sache /** 11921308Sache * Verify that NewSize and MaxNewSize flags affect young gen size. 12021308Sache * 12121308Sache * @param newSize value of NewSize option, omitted if negative 122119610Sache * @param maxNewSize value of MaxNewSize option, omitted if negative 12321308Sache * @param heapSize value of HeapSize option 12421308Sache * @param maxHeapSize value of MaxHeapSize option 12521308Sache * @param expectedNewSize expected initial young gen size 126119610Sache * @param expectedMaxNewSize expected max young gen size 12721308Sache * @param options additional options for JVM 12821308Sache * @param failureExpected true if JVM should fail with passed heap size options 12921308Sache */ 130119610Sache public static void testVMOptions(long newSize, long maxNewSize, 13121308Sache long heapSize, long maxHeapSize, 13221308Sache long expectedNewSize, long expectedMaxNewSize, 13321308Sache LinkedList<String> options, boolean failureExpected) throws Exception { 134119610Sache OutputAnalyzer analyzer = startVM(options, newSize, maxNewSize, heapSize, maxHeapSize, expectedNewSize, expectedMaxNewSize); 13521308Sache 136136644Sache if (failureExpected) { 137136644Sache analyzer.shouldHaveExitValue(1); 138136644Sache analyzer.shouldMatch("(Error occurred during initialization of VM)|" 139136644Sache + "(Error: Could not create the Java Virtual Machine.)"); 14021308Sache } else { 14121308Sache analyzer.shouldHaveExitValue(0); 142119610Sache } 14321308Sache } 14421308Sache 14521308Sache private static OutputAnalyzer startVM(LinkedList<String> options, 14621308Sache long newSize, long maxNewSize, 147119610Sache long heapSize, long maxHeapSize, 14821308Sache long expectedNewSize, long expectedMaxNewSize) throws Exception, IOException { 14921308Sache LinkedList<String> vmOptions = new LinkedList<>(options); 15021308Sache Collections.addAll(vmOptions, 15121308Sache "-Xbootclasspath/a:.", 152119610Sache "-XX:+UnlockDiagnosticVMOptions", 15321308Sache "-XX:+WhiteBoxAPI", 15421308Sache (newSize >= 0 ? "-XX:NewSize=" + newSize : ""), 15521308Sache (maxNewSize >= 0 ? "-XX:MaxNewSize=" + maxNewSize : ""), 15621308Sache "-Xmx" + maxHeapSize, 157119610Sache "-Xms" + heapSize, 15821308Sache "-XX:GCLockerEdenExpansionPercent=0", 15921308Sache "-XX:-UseLargePages", 16021308Sache NewSizeVerifier.class.getName(), 16121308Sache Long.toString(expectedNewSize), 16221308Sache Long.toString(expectedMaxNewSize), 16321308Sache Long.toString(heapSize), 16421308Sache Long.toString(maxHeapSize) 16521308Sache ); 16621308Sache vmOptions.removeIf(String::isEmpty); 167119610Sache ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()])); 16821308Sache OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); 16921308Sache return analyzer; 17047558Sache } 17147558Sache 172119610Sache /** 17321308Sache * NewSizeVerifier checks that initial young gen size is equal to expected 17421308Sache * regardful to alignment and that young gen size will not be greater than 17521308Sache * expected max size. 17621308Sache * In order to verify that young gen size will not be greater then expected 17721308Sache * max size, NewSizeVerifier do some object allocation to force garbage 17821308Sache * collection and heap expansion. 179119610Sache */ 18021308Sache public static class NewSizeVerifier { 18121308Sache 18221308Sache private static final WhiteBox WB = WhiteBox.getWhiteBox(); 18321308Sache private static final GCTypes.YoungGCType YOUNG_GC_TYPE = GCTypes.YoungGCType.getYoungGCType(); 18421308Sache private static final long HEAP_SPACE_ALIGNMENT = WB.getHeapSpaceAlignment(); 18521308Sache private static final long HEAP_ALIGNMENT = WB.getHeapAlignment(); 186119610Sache private static final long PS_VIRTUAL_SPACE_ALIGNMENT = 18721308Sache (YOUNG_GC_TYPE == GCTypes.YoungGCType.PSNew) ? WB.psVirtualSpaceAlignment() : 0; 18821308Sache 18921308Sache public static final int ARRAY_LENGTH = 100; 19021308Sache public static final int CHUNK_SIZE = 1024; 19121308Sache public static final int MAX_ITERATIONS = 10; 19221308Sache public static byte garbage[][] = new byte[ARRAY_LENGTH][]; 193119610Sache 19421308Sache public static void main(String args[]) throws Exception { 19521308Sache if (args.length != 4) { 19621308Sache throw new IllegalArgumentException("Expected 4 args: <expectedNewSize> <expectedMaxNewSize> <initialHeapSize> <maxHeapSize>"); 19721308Sache } 198119610Sache final long newSize = Long.valueOf(args[0]); 19921308Sache final long maxNewSize = Long.valueOf(args[1]); 20021308Sache final long initialHeapSize = Long.valueOf(args[2]); 20121308Sache final long maxHeapSize = Long.valueOf(args[3]); 202119610Sache 20321308Sache // verify initial size 20421308Sache verifyNewSize(newSize, maxNewSize, initialHeapSize, maxHeapSize); 205119610Sache 20621308Sache // force GC and verify that size is still correct 20721308Sache AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifyNewSize(newSize, maxNewSize, initialHeapSize, maxHeapSize))); 20821308Sache allocator.allocateMemoryAndVerifyNoOOME(); 20921308Sache } 21021308Sache 21121308Sache /** 21221308Sache * Verify that actual young gen size conforms NewSize and MaxNewSize values. 21321308Sache */ 21421308Sache public static Void verifyNewSize(long newSize, long maxNewSize, 21521308Sache long initialHeapSize, long maxHeapSize) { 21621308Sache long alignedNewSize = alignGenSize(newSize); 21721308Sache long alignedMaxNewSize = alignGenSize(maxNewSize); 21821308Sache long alignedXms = alignHeapSize(initialHeapSize); 21921308Sache long alignedXmx = alignHeapSize(maxHeapSize); 22021308Sache 221119610Sache MemoryUsage youngGenUsage = getYoungGenUsage(); 22221308Sache long initSize = youngGenUsage.getInit(); 22321308Sache long commitedSize = youngGenUsage.getCommitted(); 22421308Sache long maxSize = youngGenUsage.getMax(); 22521308Sache 226119610Sache if (newSize != -1) { 22721308Sache if (initSize < alignedNewSize) { 22821308Sache throw new RuntimeException("initial new size < NewSize value: " 22947558Sache + initSize + " < " + alignedNewSize); 23047558Sache } 23147558Sache 23247558Sache if (commitedSize < alignedNewSize) { 23347558Sache throw new RuntimeException("actual new size < NewSize value: " 234119610Sache + commitedSize + " < " + alignedNewSize); 23521308Sache } 23621308Sache 23721308Sache // for G1 max new size == committed new size 238119610Sache if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1 23921308Sache && maxSize < alignedNewSize) { 24021308Sache throw new RuntimeException("max new size < NewSize value: " 24121308Sache + maxSize + " < " + alignedNewSize); 24221308Sache } 24375406Sache } 24421308Sache 24521308Sache if (maxNewSize != -1) { 24675406Sache if (initSize > alignedMaxNewSize) { 24721308Sache throw new RuntimeException("initial new size > MaxNewSize value: " 24821308Sache + initSize + " > " + alignedMaxNewSize); 24921308Sache } 25021308Sache 25121308Sache if (commitedSize > alignedMaxNewSize) { 252136644Sache throw new RuntimeException("actual new size > MaxNewSize value: " 253136644Sache + commitedSize + " > " + alignedMaxNewSize); 25475406Sache } 25575406Sache 25675406Sache if (alignedXms != alignedXmx) { 25726497Sache if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1 25826497Sache && maxSize != alignedMaxNewSize) { 25926497Sache throw new RuntimeException("max new size != MaxNewSize value: " 26075406Sache + maxSize + " != " + alignedMaxNewSize); 26126497Sache } 26247558Sache } else { 26347558Sache if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1 26447558Sache && maxSize != alignedNewSize) { 26547558Sache throw new RuntimeException("max new size != NewSize for case InitialHeapSize == MaxHeapSize value: " 26621308Sache + maxSize + " != " + alignedNewSize + " HeapSize == " + alignedXms); 267 } 268 } 269 } 270 return null; 271 } 272 273 /** 274 * Get young gen memory usage. 275 * 276 * For G1 it is EdenUsage + SurvivorUsage, 277 * for other GCs it is EdenUsage + 2 * SurvivorUsage. 278 * For G1 max value is just LONG_MAX. 279 * For all GCs used value is 0. 280 */ 281 private static MemoryUsage getYoungGenUsage() { 282 MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage(); 283 MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage(); 284 long edenUsageInit = edenUsage.getInit(); 285 long edenUsageCommited = edenUsage.getCommitted(); 286 long survivorUsageInit = survivorUsage.getInit(); 287 long survivorUsageCommited = survivorUsage.getCommitted(); 288 289 if (YOUNG_GC_TYPE == GCTypes.YoungGCType.G1) { 290 return new MemoryUsage(edenUsageInit + survivorUsageInit, 0, 291 edenUsageCommited + survivorUsageCommited, Long.MAX_VALUE); 292 } else { 293 return new MemoryUsage(edenUsageInit + survivorUsageInit * 2, 0, 294 edenUsageCommited + survivorUsageCommited * 2, 295 edenUsage.getMax() + survivorUsage.getMax() * 2); 296 } 297 } 298 299 /** 300 * Align generation size regardful to used young GC. 301 */ 302 public static long alignGenSize(long value) { 303 switch (YOUNG_GC_TYPE) { 304 case DefNew: 305 case ParNew: 306 return HeapRegionUsageTool.alignDown(value, HEAP_SPACE_ALIGNMENT); 307 case PSNew: 308 return HeapRegionUsageTool.alignUp(HeapRegionUsageTool.alignDown(value, 309 HEAP_SPACE_ALIGNMENT), 310 PS_VIRTUAL_SPACE_ALIGNMENT); 311 case G1: 312 return HeapRegionUsageTool.alignUp(value, WB.g1RegionSize()); 313 default: 314 throw new RuntimeException("Unexpected young GC type"); 315 } 316 } 317 318 /** 319 * Align heap size. 320 */ 321 public static long alignHeapSize(long value){ 322 return HeapRegionUsageTool.alignUp(value,HEAP_ALIGNMENT); 323 } 324 } 325} 326