Path: blob/master/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java
40942 views
/*1* Copyright (c) 2016, 2020, 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 TestMaxMinHeapFreeRatioFlags27* @summary Verify that heap size changes according to max and min heap free ratios.28* @requires vm.gc != "Z" & vm.gc != "Shenandoah"29* @library /test/lib30* @library /31* @modules java.base/jdk.internal.misc32* java.management33* @run driver/timeout=240 gc.arguments.TestMaxMinHeapFreeRatioFlags34*/3536import java.util.LinkedList;37import java.util.Arrays;38import java.util.Collections;39import jdk.test.lib.process.OutputAnalyzer;40import jdk.test.lib.process.ProcessTools;41import jdk.test.lib.Utils;42import jdk.internal.misc.Unsafe;4344public class TestMaxMinHeapFreeRatioFlags {4546public static final long M = 1024 * 1024;47public static final long MAX_HEAP_SIZE = 200 * M;48public static final long HEAP_SIZE = 10 * M;49public static final long MAX_NEW_SIZE = 20 * M;50public static final long NEW_SIZE = 5 * M;5152public static void main(String args[]) throws Exception {53LinkedList<String> options = new LinkedList<>(54Arrays.asList(Utils.getFilteredTestJavaOpts("-XX:[^ ]*HeapFreeRatio","-XX:\\+ExplicitGCInvokesConcurrent"))55);5657negativeTest(20, false, 10, true, options);58negativeTest(100, true, 0, false, options);59negativeTest(101, false, 50, false, options);60negativeTest(49, true, 102, true, options);61negativeTest(-1, false, 50, false, options);62negativeTest(50, true, -1, true, options);6364positiveTest(10, false, 90, false, true, options);65positiveTest(10, true, 80, false, true, options);66positiveTest(20, false, 70, true, true, options);67positiveTest(25, true, 65, true, true, options);68positiveTest(40, false, 50, false, true, options);69}7071/**72* Verify that heap size will be changed to conform73* min and max heap free ratios.74*75* @param minRatio value of MinHeapFreeRatio option76* @param useXminf used Xminf option instead of MinHeapFreeRatio77* @param maxRatio value of MaxHeapFreeRatio option78* @param useXmaxf used Xmaxf option instead of MaxHeapFreeRatio79* @param options additional options for JVM80*/81public static void positiveTest(int minRatio, boolean useXminf,82int maxRatio, boolean useXmaxf, boolean shrinkHeapInSteps,83LinkedList<String> options) throws Exception {8485LinkedList<String> vmOptions = new LinkedList<>(options);86Collections.addAll(vmOptions,87(useXminf ? "-Xminf" + minRatio / 100.0 : "-XX:MinHeapFreeRatio=" + minRatio),88(useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),89"-Xmx" + MAX_HEAP_SIZE,90"-Xms" + HEAP_SIZE,91"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",92"-XX:NewSize=" + NEW_SIZE,93"-XX:MaxNewSize=" + MAX_NEW_SIZE,94"-XX:" + (shrinkHeapInSteps ? '+' : '-') + "ShrinkHeapInSteps",95RatioVerifier.class.getName(),96Integer.toString(minRatio),97Integer.toString(maxRatio),98Boolean.toString(shrinkHeapInSteps)99);100101ProcessBuilder procBuilder = GCArguments.createJavaProcessBuilder(vmOptions);102OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());103analyzer.shouldHaveExitValue(0);104}105106/**107* Verify that VM will fail to start with specified ratios.108*109* @param minRatio value of MinHeapFreeRatio option110* @param useXminf used Xminf option instead of MinHeapFreeRatio111* @param maxRatio value of MaxHeapFreeRatio option112* @param useXmaxf used Xmaxf option instead of MaxHeapFreeRatio113* @param options additional options for JVM114*/115public static void negativeTest(int minRatio, boolean useXminf,116int maxRatio, boolean useXmaxf,117LinkedList<String> options) throws Exception {118119LinkedList<String> vmOptions = new LinkedList<>(options);120Collections.addAll(vmOptions,121(useXminf ? "-Xminf" + minRatio / 100.0 : "-XX:MinHeapFreeRatio=" + minRatio),122(useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),123"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",124"-version"125);126ProcessBuilder procBuilder = GCArguments.createJavaProcessBuilder(vmOptions);127OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start());128analyzer.shouldHaveExitValue(1);129analyzer.shouldContain("Error: Could not create the Java Virtual Machine.");130}131132/**133* RatioVerifier will be executed in the tested VM.134* It will check that real heap usage after collection lies between MinHeapFreeRatio and MaxHeapFreeRatio.135*/136public static class RatioVerifier {137138private static final Unsafe unsafe = Unsafe.getUnsafe();139140// Size of byte array that will be allocated141public static final int CHUNK_SIZE = 1024;142// Length of byte array, that will be added to "garbage" list.143public static final int ARRAY_LENGTH = CHUNK_SIZE - Unsafe.ARRAY_BYTE_BASE_OFFSET;144// Amount of tries to force heap shrinking/expansion using GC145public static final int GC_TRIES = 10;146147// Value that will be added/substracted from expected min/max heap free ratio148// during memory allocation to make sure that specified limit will be exceeded.149public static final double OVERLOAD = 0.05;150// Acceptable heap free ratio limit exceedance: verification will fail if151// actual ratio is lower than expected min heap free ratio - VARIANCE or152// higher than expected max heap free ratio + VARIANCE.153public static final double VARIANCE = 0.025;154155public static LinkedList<Object> garbage = new LinkedList<>();156157public static void main(String args[]) throws Exception {158if (args.length != 3) {159throw new IllegalArgumentException("Expected 3 args: <minRatio> <maxRatio> <shrinkHeapInSteps>");160}161if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.PSOld ||162GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {163System.out.println("Test is not applicable to parallel full GCs");164return;165}166167double minRatio = Integer.valueOf(args[0]) / 100.0;168double maxRatio = Integer.valueOf(args[1]) / 100.0;169boolean shrinkHeapInSteps = Boolean.valueOf(args[2]);170171long maxHeapSize = getMax();172int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1);173174// Initial checks. This also links up everything in these helper methods,175// in case it brings more garbage.176forceGC(gcTries);177verifyRatio(minRatio, maxRatio);178179// commit 0.5 of total heap size to have enough space180// to both shink and expand181while (getCommitted() < maxHeapSize / 2) {182garbage.add(new byte[ARRAY_LENGTH]);183}184185forceGC(gcTries);186// Verify that current heap free ratio lies between specified limits187verifyRatio(minRatio, maxRatio);188189// Estimate how much memory we have to allocate to force expansion190long memoryToFill = (long) (getCommitted() * (1 - minRatio + OVERLOAD))191- getUsed();192193long previouslyCommitted = getCommitted();194195while (memoryToFill > 0) {196garbage.add(new byte[CHUNK_SIZE]);197memoryToFill -= CHUNK_SIZE;198}199200forceGC(gcTries);201// Verify that after memory allocation heap free ratio is still conforming specified limits202verifyRatio(minRatio, maxRatio);203// Verify that heap was actually expanded204if (previouslyCommitted >= getCommitted()) {205throw new RuntimeException("Heap was not expanded.");206}207208// Estimate how much memory we have to free to force shrinking209long memoryToFree = getUsed()210- (long) (getCommitted() * (1 - maxRatio - OVERLOAD));211212previouslyCommitted = getCommitted();213214while (memoryToFree > 0 && garbage.size() > 0) {215garbage.remove(garbage.size() - 1);216memoryToFree -= CHUNK_SIZE;217}218219forceGC(gcTries);220// Verify that heap free ratio is still conforming specified limits221verifyRatio(minRatio, maxRatio);222// Verify that heap was actually shrinked223if (previouslyCommitted <= getCommitted()) {224throw new RuntimeException("Heap was not shrinked.");225}226}227228public static void forceGC(int gcTries) {229for (int i = 0; i < gcTries; i++) {230System.gc();231try {232Thread.sleep(10);233} catch (InterruptedException ie) {234}235}236}237238/**239* Verify that heap free ratio is conforming specified limits.240* Actual heap free ratio may be very close to one of specified limits,241* but exceed for more then VARIANCE.242* Verification will also pass if actual ratio is not conforming limits,243* but it is not possible to shrink/expand heap.244*/245public static void verifyRatio(double minRatio, double maxRatio) {246double ratio = getHeapFreeRatio();247System.out.println(minRatio + " " + ratio + " " + maxRatio);248if (minRatio - ratio > VARIANCE249&& getCommitted() < getMax()) {250throw new RuntimeException("Current heap free ratio is lower than "251+ "MinHeapFreeRatio (" + ratio + " vs " + minRatio + ").");252}253if (ratio - maxRatio > VARIANCE254&& getUsed() > getInit()) {255throw new RuntimeException("Current heap free ratio is higher than "256+ "MaxHeapFreeRatio (" + ratio + " vs " + maxRatio + ").");257}258}259260/*261* Obtain information about heap size.262*263* For G1 information summed up for all type of regions,264* because tested options affect overall heap sizing.265*266* For all other GCs return information only for old gen.267*/268public static long getMax() {269return HeapRegionUsageTool.getOldUsage().getMax();270}271272public static long getInit() {273if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {274return HeapRegionUsageTool.getEdenUsage().getInit()275+ HeapRegionUsageTool.getSurvivorUsage().getInit()276+ HeapRegionUsageTool.getOldUsage().getInit();277} else {278return HeapRegionUsageTool.getOldUsage().getInit();279}280}281282public static long getUsed() {283if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {284return HeapRegionUsageTool.getEdenUsage().getUsed()285+ HeapRegionUsageTool.getSurvivorUsage().getUsed()286+ HeapRegionUsageTool.getOldUsage().getUsed();287} else {288return HeapRegionUsageTool.getOldUsage().getUsed();289}290}291292public static long getCommitted() {293if (GCTypes.OldGCType.getOldGCType() == GCTypes.OldGCType.G1) {294return HeapRegionUsageTool.getEdenUsage().getCommitted()295+ HeapRegionUsageTool.getSurvivorUsage().getCommitted()296+ HeapRegionUsageTool.getOldUsage().getCommitted();297} else {298return HeapRegionUsageTool.getOldUsage().getCommitted();299}300}301302public static long getFree() {303return getCommitted() - getUsed();304}305306public static double getHeapFreeRatio() {307return getFree() / (double) getCommitted();308}309}310}311312313