1 /* 2 * Copyright (c) 2003, 2016, 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 /* 25 * The -XX:MarkSweepAlwaysCompactCount=1 argument below makes sure serial gc 26 * compacts the heap at every full gc so that the usage is correctly updated. 27 */ 28 29 /* 30 * @test 31 * @bug 4892507 32 * @summary Basic Test for MemoryPool.resetPeakUsage() 33 * @author Mandy Chung 34 * 35 * @library /lib/testlibrary/ 36 * @modules jdk.management 37 * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil 38 * @run main ResetPeakMemoryUsage 39 * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" 40 * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true" 41 * @requires vm.opt.DisableExplicitGC != "true" 42 */ 43 44 import java.lang.management.*; 45 import java.lang.ref.WeakReference; 46 import java.util.*; 47 48 public class ResetPeakMemoryUsage { 49 private static MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); 50 // make public so that it can't be optimized away easily 51 public static Object[] obj; 52 53 /** 54 * Run the test multiple times with different GC versions. 55 * First with default command line specified by the framework. 56 * Then with all GC versions specified by the test. 57 */ 58 public static void main(String a[]) throws Throwable { 59 final String main = "ResetPeakMemoryUsage$TestMain"; 60 final String ms = "-Xms256m"; 61 final String mn = "-Xmn8m"; 62 RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC"); 63 RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseParallelGC"); 64 RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1m"); 65 RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseSerialGC", 66 "-XX:MarkSweepAlwaysCompactCount=1"); 67 } 68 69 private static class TestMain { 70 public static void main(String[] argv) { 71 List pools = ManagementFactory.getMemoryPoolMXBeans(); 72 ListIterator iter = pools.listIterator(); 73 boolean found = false; 74 while (iter.hasNext()) { 75 MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next(); 76 // only check heap pools that support usage threshold 77 // this is typically only the old generation space 78 // since the other spaces are expected to get filled up 79 if (p.getType() == MemoryType.HEAP && 80 p.isUsageThresholdSupported()) 81 { 82 found = true; 83 testPool(p); 84 } 85 } 86 if (!found) { 87 throw new RuntimeException("No heap pool found"); 88 } 89 } 90 } 91 92 private static void testPool(MemoryPoolMXBean mpool) { 93 System.out.println("Selected memory pool: "); 94 MemoryUtil.printMemoryPool(mpool); 95 96 MemoryUsage usage0 = mpool.getUsage(); 97 MemoryUsage peak0 = mpool.getPeakUsage(); 98 99 // use a size that is larger than the young generation and G1 regions 100 // to force the array into the old gen 101 int largeArraySize = 9 * 1000 * 1000; 102 103 System.out.println("Before big object array (of size "+largeArraySize+") is allocated: "); 104 printMemoryUsage(usage0, peak0); 105 106 obj = new Object[largeArraySize]; 107 WeakReference<Object> weakRef = new WeakReference<>(obj); 108 109 MemoryUsage usage1 = mpool.getUsage(); 110 MemoryUsage peak1 = mpool.getPeakUsage(); 111 System.out.println("After the object is allocated: "); 112 printMemoryUsage(usage1, peak1); 113 114 if (usage1.getUsed() <= usage0.getUsed()) { 115 throw new RuntimeException( 116 formatSize("Before allocation: used", usage0.getUsed()) + 117 " expected to be < " + 118 formatSize("After allocation: used", usage1.getUsed())); 119 } 120 121 if (peak1.getUsed() <= peak0.getUsed()) { 122 throw new RuntimeException( 123 formatSize("Before allocation: peak", peak0.getUsed()) + 124 " expected to be < " + 125 formatSize("After allocation: peak", peak1.getUsed())); 126 } 127 128 129 // The object is now garbage and do a GC 130 // memory usage should drop 131 obj = null; 132 133 //This will cause sure shot GC unlike Runtime.gc() invoked by mbean.gc() 134 while(weakRef.get() != null) { 135 mbean.gc(); 136 } 137 138 MemoryUsage usage2 = mpool.getUsage(); 139 MemoryUsage peak2 = mpool.getPeakUsage(); 140 System.out.println("After GC: "); 141 printMemoryUsage(usage2, peak2); 142 143 if (usage2.getUsed() >= usage1.getUsed()) { 144 throw new RuntimeException( 145 formatSize("Before GC: used", usage1.getUsed()) + " " + 146 " expected to be > " + 147 formatSize("After GC: used", usage2.getUsed())); 148 } 149 150 mpool.resetPeakUsage(); 151 152 MemoryUsage usage3 = mpool.getUsage(); 153 MemoryUsage peak3 = mpool.getPeakUsage(); 154 System.out.println("After resetPeakUsage: "); 155 printMemoryUsage(usage3, peak3); 156 157 if (peak3.getUsed() != usage3.getUsed()) { 158 throw new RuntimeException( 159 formatSize("After resetting peak: peak", peak3.getUsed()) + " " + 160 " expected to be equal to " + 161 formatSize("current used", usage3.getUsed())); 162 } 163 164 if (peak3.getUsed() >= peak2.getUsed()) { 165 throw new RuntimeException( 166 formatSize("After resetting peak: peak", peak3.getUsed()) + " " + 167 " expected to be < " + 168 formatSize("previous peak", peak2.getUsed())); 169 } 170 171 System.out.println(RunUtil.successMessage); 172 } 173 174 private static String INDENT = " "; 175 private static void printMemoryUsage(MemoryUsage current, MemoryUsage peak) { 176 System.out.println("Current Usage: "); 177 MemoryUtil.printMemoryUsage(current); 178 System.out.println("Peak Usage: "); 179 MemoryUtil.printMemoryUsage(peak); 180 181 } 182 private static String formatSize(String name, long value) { 183 StringBuffer buf = new StringBuffer(name + " = " + value); 184 if (value > 0) { 185 buf.append(" (" + (value >> 10) + "K)"); 186 } 187 return buf.toString(); 188 } 189 }