Path: blob/master/test/hotspot/jtreg/gc/g1/TestHumongousShrinkHeap.java
40942 views
/*1* Copyright (c) 2014, 2019, 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.g1;2425/**26* @test TestHumongousShrinkHeap27* @bug 8036025 805604328* @requires vm.gc.G129* @summary Verify that heap shrinks after GC in the presence of fragmentation30* due to humongous objects31* @library /test/lib /32* @modules java.base/jdk.internal.misc33* @modules java.management/sun.management34* @run main/othervm -XX:-ExplicitGCInvokesConcurrent -XX:MinHeapFreeRatio=1035* -XX:MaxHeapFreeRatio=12 -XX:+UseG1GC -XX:G1HeapRegionSize=1M -verbose:gc36* gc.g1.TestHumongousShrinkHeap37*/3839import com.sun.management.HotSpotDiagnosticMXBean;40import java.lang.management.ManagementFactory;41import java.lang.management.MemoryUsage;42import java.util.ArrayList;43import java.util.List;44import java.text.NumberFormat;45import gc.testlibrary.Helpers;46import static jdk.test.lib.Asserts.*;47import jtreg.SkippedException;4849public class TestHumongousShrinkHeap {5051public static final String MIN_FREE_RATIO_FLAG_NAME = "MinHeapFreeRatio";52public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio";5354private static final List<List<byte[]>> garbage = new ArrayList<>();55private static final int REGION_SIZE = 1024 * 1024; // 1M56private static final int LISTS_COUNT = 10;57private static final int HUMON_SIZE = Math.round(.9f * REGION_SIZE);5859private static final long TOTAL_MEMORY = Runtime.getRuntime().totalMemory();60private static final long MAX_MEMORY = Runtime.getRuntime().maxMemory();6162private static final int HUMON_COUNT = (int) ((TOTAL_MEMORY / HUMON_SIZE) / LISTS_COUNT);6364public static void main(String[] args) {65if (HUMON_COUNT == 0) {66throw new SkippedException("Heap is too small");67}6869if (TOTAL_MEMORY + REGION_SIZE * HUMON_COUNT > MAX_MEMORY) {70throw new SkippedException("Initial heap size is to close to max heap size.");71}7273System.out.format("Running with %s initial heap size of %s maximum heap size. "74+ "Will allocate humongous object of %s size %d times.%n",75MemoryUsagePrinter.NF.format(TOTAL_MEMORY),76MemoryUsagePrinter.NF.format(MAX_MEMORY),77MemoryUsagePrinter.NF.format(HUMON_SIZE),78HUMON_COUNT79);80new TestHumongousShrinkHeap().test();81}8283private final void test() {84System.gc();85MemoryUsagePrinter.printMemoryUsage("init");8687allocate();88MemoryUsagePrinter.printMemoryUsage("allocated");89MemoryUsage muFull = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();9091free();92MemoryUsagePrinter.printMemoryUsage("free");93MemoryUsage muFree = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();9495assertLessThan(muFree.getCommitted(), muFull.getCommitted(), String.format(96"committed free heap size is not less than committed full heap size, heap hasn't been shrunk?%n"97+ "%s = %s%n%s = %s",98MIN_FREE_RATIO_FLAG_NAME,99ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class)100.getVMOption(MIN_FREE_RATIO_FLAG_NAME).getValue(),101MAX_FREE_RATIO_FLAG_NAME,102ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class)103.getVMOption(MAX_FREE_RATIO_FLAG_NAME).getValue()104));105}106107private void allocate() {108109for (int i = 0; i < LISTS_COUNT; i++) {110List<byte[]> stuff = new ArrayList<>();111allocateList(stuff, HUMON_COUNT, HUMON_SIZE);112MemoryUsagePrinter.printMemoryUsage("allocate #" + (i+1));113garbage.add(stuff);114}115}116117private void free() {118// do not free last one list119garbage.subList(0, garbage.size() - 1).clear();120121// do not free last one element from last list122List<byte[]> stuff = garbage.get(garbage.size() - 1);123stuff.subList(0, stuff.size() - 1).clear();124System.gc();125}126127private static void allocateList(List<byte[]> garbage, int count, int size) {128for (int i = 0; i < count; i++) {129garbage.add(new byte[size]);130}131}132}133134/**135* Prints memory usage to standard output136*/137class MemoryUsagePrinter {138139public static final NumberFormat NF = Helpers.numberFormatter();140141public static void printMemoryUsage(String label) {142MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();143float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();144System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",145label,146NF.format(memusage.getInit()),147NF.format(memusage.getUsed()),148NF.format(memusage.getCommitted()),149freeratio * 100150);151}152}153154155