Path: blob/master/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java
40948 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package gc.arguments;2425/*26* @test TestNewSizeFlags27* @bug 802516628* @summary Verify that young gen size conforms values specified by NewSize, MaxNewSize and Xmn options29* @requires vm.gc != "Z" & vm.gc != "Shenandoah"30* @library /test/lib31* @library /32* @modules java.base/jdk.internal.misc33* java.management34* @build sun.hotspot.WhiteBox35* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox36* @run driver/timeout=240 gc.arguments.TestNewSizeFlags37*/3839import java.io.IOException;40import java.lang.management.MemoryUsage;41import java.util.Arrays;42import java.util.Collections;43import java.util.LinkedList;44import jdk.test.lib.process.OutputAnalyzer;45import jdk.test.lib.process.ProcessTools;46import jdk.test.lib.Utils;47import sun.hotspot.WhiteBox;4849public class TestNewSizeFlags {5051public static final long M = 1024 * 1024;5253public static void main(String args[]) throws Exception {54LinkedList<String> options = new LinkedList<>(55Arrays.asList(Utils.getFilteredTestJavaOpts("(-Xm[nsx][^ ]+)|"56+ "(-XX:(Max)?((New)|"57+ "(Heap))((Size)|"58+ "(Ratio))=[^ ]+)"))59);6061// Test NewSize and MaxNewSize62testNewSizeFlags(20 * M, 10 * M, 30 * M, 40 * M, options, false);63testNewSizeFlags(10 * M, 20 * M, 30 * M, 80 * M, options, false);64testNewSizeFlags(-1, 20 * M, 30 * M, 40 * M, options, false);65testNewSizeFlags(10 * M, -1, 30 * M, 40 * M, options, false);66testNewSizeFlags(20 * M, 20 * M, 30 * M, 40 * M, options, false);67testNewSizeFlags(20 * M, 30 * M, 40 * M, 50 * M, options, false);68testNewSizeFlags(30 * M, 100 * M, 150 * M, 200 * M, options, false);69testNewSizeFlags(20 * M, 30 * M, 128 * M, 128 * M, options, false);7071// Test -Xmn72testXmnFlags(0, 30 * M, 40 * M, options, true);73testXmnFlags(20 * M, 30 * M, 40 * M, options, false);74testXmnFlags(50 * M, 70 * M, 100 * M, options, false);75}7677/**78* Verify that NewSize and MaxNewSize flags affect young gen size.79*80* @param newSize value of NewSize option, omitted if negative81* @param maxNewSize value of MaxNewSize option, omitted if negative82* @param heapSize value of HeapSize option83* @param maxHeapSize value of MaxHeapSize option84* @param options additional options for JVM85* @param failureExpected true if JVM should fail with passed heap size options86*/87public static void testNewSizeFlags(long newSize, long maxNewSize,88long heapSize, long maxHeapSize,89LinkedList<String> options,90boolean failureExpected) throws Exception {91long expectedNewSize = newSize;92long expectedMaxNewSize = (maxNewSize >= 0 ? Math.max(maxNewSize, newSize) : maxNewSize);93testVMOptions(newSize, maxNewSize,94heapSize, maxHeapSize,95expectedNewSize, expectedMaxNewSize,96options, failureExpected);97}9899/**100* Verify that -Xmn flag affect young gen size.101*102* @param mnValue value of -Xmn option103* @param heapSize value of HeapSize option104* @param maxHeapSize value of MaxHeapSize option105* @param options additional options for JVM106* @param failureExpected true if JVM should fail with passed heap size options107*/108public static void testXmnFlags(long mnValue,109long heapSize, long maxHeapSize,110LinkedList<String> options,111boolean failureExpected) throws Exception {112LinkedList<String> newOptions = new LinkedList<>(options);113newOptions.add("-Xmn" + mnValue);114testVMOptions(-1, -1,115heapSize, maxHeapSize,116mnValue, mnValue,117newOptions, failureExpected);118}119120/**121* Verify that NewSize and MaxNewSize flags affect young gen size.122*123* @param newSize value of NewSize option, omitted if negative124* @param maxNewSize value of MaxNewSize option, omitted if negative125* @param heapSize value of HeapSize option126* @param maxHeapSize value of MaxHeapSize option127* @param expectedNewSize expected initial young gen size128* @param expectedMaxNewSize expected max young gen size129* @param options additional options for JVM130* @param failureExpected true if JVM should fail with passed heap size options131*/132public static void testVMOptions(long newSize, long maxNewSize,133long heapSize, long maxHeapSize,134long expectedNewSize, long expectedMaxNewSize,135LinkedList<String> options, boolean failureExpected) throws Exception {136OutputAnalyzer analyzer = startVM(options, newSize, maxNewSize, heapSize, maxHeapSize, expectedNewSize, expectedMaxNewSize);137138if (failureExpected) {139analyzer.shouldHaveExitValue(1);140analyzer.shouldMatch("(Error occurred during initialization of VM)|"141+ "(Error: Could not create the Java Virtual Machine.)");142} else {143analyzer.shouldHaveExitValue(0);144}145}146147private static OutputAnalyzer startVM(LinkedList<String> options,148long newSize, long maxNewSize,149long heapSize, long maxHeapSize,150long expectedNewSize, long expectedMaxNewSize) throws Exception, IOException {151LinkedList<String> vmOptions = new LinkedList<>(options);152Collections.addAll(vmOptions,153"-Xbootclasspath/a:.",154"-XX:+UnlockDiagnosticVMOptions",155"-XX:+WhiteBoxAPI",156(newSize >= 0 ? "-XX:NewSize=" + newSize : ""),157(maxNewSize >= 0 ? "-XX:MaxNewSize=" + maxNewSize : ""),158"-Xmx" + maxHeapSize,159"-Xms" + heapSize,160"-XX:GCLockerEdenExpansionPercent=0",161"-XX:-UseLargePages",162NewSizeVerifier.class.getName(),163Long.toString(expectedNewSize),164Long.toString(expectedMaxNewSize),165Long.toString(heapSize),166Long.toString(maxHeapSize)167);168vmOptions.removeIf(String::isEmpty);169ProcessBuilder procBuilder = GCArguments.createJavaProcessBuilder(vmOptions);170OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());171return analyzer;172}173174/**175* NewSizeVerifier checks that initial young gen size is equal to expected176* regardful to alignment and that young gen size will not be greater than177* expected max size.178* In order to verify that young gen size will not be greater then expected179* max size, NewSizeVerifier do some object allocation to force garbage180* collection and heap expansion.181*/182public static class NewSizeVerifier {183184private static final WhiteBox WB = WhiteBox.getWhiteBox();185private static final GCTypes.YoungGCType YOUNG_GC_TYPE = GCTypes.YoungGCType.getYoungGCType();186private static final long HEAP_SPACE_ALIGNMENT = WB.getHeapSpaceAlignment();187private static final long HEAP_ALIGNMENT = WB.getHeapAlignment();188private static final long PS_VIRTUAL_SPACE_ALIGNMENT =189(YOUNG_GC_TYPE == GCTypes.YoungGCType.PSNew) ? WB.psVirtualSpaceAlignment() : 0;190191public static final int ARRAY_LENGTH = 100;192public static final int CHUNK_SIZE = 1024;193public static final int MAX_ITERATIONS = 10;194public static byte garbage[][] = new byte[ARRAY_LENGTH][];195196public static void main(String args[]) throws Exception {197if (args.length != 4) {198throw new IllegalArgumentException("Expected 4 args: <expectedNewSize> <expectedMaxNewSize> <initialHeapSize> <maxHeapSize>");199}200final long newSize = Long.valueOf(args[0]);201final long maxNewSize = Long.valueOf(args[1]);202final long initialHeapSize = Long.valueOf(args[2]);203final long maxHeapSize = Long.valueOf(args[3]);204205// verify initial size206verifyNewSize(newSize, maxNewSize, initialHeapSize, maxHeapSize);207208// force GC and verify that size is still correct209AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE, () -> (verifyNewSize(newSize, maxNewSize, initialHeapSize, maxHeapSize)));210allocator.allocateMemoryAndVerifyNoOOME();211}212213/**214* Verify that actual young gen size conforms NewSize and MaxNewSize values.215*/216public static Void verifyNewSize(long newSize, long maxNewSize,217long initialHeapSize, long maxHeapSize) {218long alignedNewSize = alignGenSize(newSize);219long alignedMaxNewSize = alignGenSize(maxNewSize);220long alignedXms = alignHeapSize(initialHeapSize);221long alignedXmx = alignHeapSize(maxHeapSize);222223MemoryUsage youngGenUsage = getYoungGenUsage();224long initSize = youngGenUsage.getInit();225long commitedSize = youngGenUsage.getCommitted();226long maxSize = youngGenUsage.getMax();227228if (newSize != -1) {229if (initSize < alignedNewSize) {230throw new RuntimeException("initial new size < NewSize value: "231+ initSize + " < " + alignedNewSize);232}233234if (commitedSize < alignedNewSize) {235throw new RuntimeException("actual new size < NewSize value: "236+ commitedSize + " < " + alignedNewSize);237}238239// for G1 max new size == committed new size240if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1241&& maxSize < alignedNewSize) {242throw new RuntimeException("max new size < NewSize value: "243+ maxSize + " < " + alignedNewSize);244}245}246247if (maxNewSize != -1) {248if (initSize > alignedMaxNewSize) {249throw new RuntimeException("initial new size > MaxNewSize value: "250+ initSize + " > " + alignedMaxNewSize);251}252253if (commitedSize > alignedMaxNewSize) {254throw new RuntimeException("actual new size > MaxNewSize value: "255+ commitedSize + " > " + alignedMaxNewSize);256}257258if (alignedXms != alignedXmx) {259if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1260&& maxSize != alignedMaxNewSize) {261throw new RuntimeException("max new size != MaxNewSize value: "262+ maxSize + " != " + alignedMaxNewSize);263}264} else {265if (YOUNG_GC_TYPE != GCTypes.YoungGCType.G1266&& maxSize != alignedNewSize) {267throw new RuntimeException("max new size != NewSize for case InitialHeapSize == MaxHeapSize value: "268+ maxSize + " != " + alignedNewSize + " HeapSize == " + alignedXms);269}270}271}272return null;273}274275/**276* Get young gen memory usage.277*278* For G1 it is EdenUsage + SurvivorUsage,279* for other GCs it is EdenUsage + 2 * SurvivorUsage.280* For G1 max value is just LONG_MAX.281* For all GCs used value is 0.282*/283private static MemoryUsage getYoungGenUsage() {284MemoryUsage edenUsage = HeapRegionUsageTool.getEdenUsage();285MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();286long edenUsageInit = edenUsage.getInit();287long edenUsageCommited = edenUsage.getCommitted();288long survivorUsageInit = survivorUsage.getInit();289long survivorUsageCommited = survivorUsage.getCommitted();290291if (YOUNG_GC_TYPE == GCTypes.YoungGCType.G1) {292return new MemoryUsage(edenUsageInit + survivorUsageInit, 0,293edenUsageCommited + survivorUsageCommited, Long.MAX_VALUE);294} else {295return new MemoryUsage(edenUsageInit + survivorUsageInit * 2, 0,296edenUsageCommited + survivorUsageCommited * 2,297edenUsage.getMax() + survivorUsage.getMax() * 2);298}299}300301/**302* Align generation size regardful to used young GC.303*/304public static long alignGenSize(long value) {305switch (YOUNG_GC_TYPE) {306case DefNew:307return HeapRegionUsageTool.alignDown(value, HEAP_SPACE_ALIGNMENT);308case PSNew:309return HeapRegionUsageTool.alignUp(HeapRegionUsageTool.alignDown(value,310HEAP_SPACE_ALIGNMENT),311PS_VIRTUAL_SPACE_ALIGNMENT);312case G1:313return HeapRegionUsageTool.alignUp(value, WB.g1RegionSize());314default:315throw new RuntimeException("Unexpected young GC type");316}317}318319/**320* Align heap size.321*/322public static long alignHeapSize(long value){323return HeapRegionUsageTool.alignUp(value,HEAP_ALIGNMENT);324}325}326}327328329