Tue, 17 Sep 2013 20:59:07 +0200
8024718: Metaspace performance counters and memory pools should report the same data
Reviewed-by: stefank, dholmes, coleenp
1.1 --- a/src/share/vm/memory/metaspaceCounters.cpp Wed Sep 18 00:08:00 2013 +0000 1.2 +++ b/src/share/vm/memory/metaspaceCounters.cpp Tue Sep 17 20:59:07 2013 +0200 1.3 @@ -65,26 +65,25 @@ 1.4 1.5 MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL; 1.6 1.7 -size_t MetaspaceCounters::calculate_capacity() { 1.8 - // The total capacity is the sum of 1.9 - // 1) capacity of Metachunks in use by all Metaspaces 1.10 - // 2) unused space at the end of each Metachunk 1.11 - // 3) space in the freelist 1.12 - size_t total_capacity = MetaspaceAux::allocated_capacity_bytes() 1.13 - + MetaspaceAux::free_bytes() + MetaspaceAux::free_chunks_total_bytes(); 1.14 - return total_capacity; 1.15 +size_t MetaspaceCounters::used() { 1.16 + return MetaspaceAux::allocated_used_bytes(); 1.17 +} 1.18 + 1.19 +size_t MetaspaceCounters::capacity() { 1.20 + return MetaspaceAux::committed_bytes(); 1.21 +} 1.22 + 1.23 +size_t MetaspaceCounters::max_capacity() { 1.24 + return MetaspaceAux::reserved_bytes(); 1.25 } 1.26 1.27 void MetaspaceCounters::initialize_performance_counters() { 1.28 if (UsePerfData) { 1.29 assert(_perf_counters == NULL, "Should only be initialized once"); 1.30 1.31 - size_t min_capacity = MetaspaceAux::min_chunk_size_bytes(); 1.32 - size_t capacity = calculate_capacity(); 1.33 - size_t max_capacity = MetaspaceAux::reserved_bytes(); 1.34 - size_t used = MetaspaceAux::allocated_used_bytes(); 1.35 - 1.36 - _perf_counters = new MetaspacePerfCounters("metaspace", min_capacity, capacity, max_capacity, used); 1.37 + size_t min_capacity = 0; 1.38 + _perf_counters = new MetaspacePerfCounters("metaspace", min_capacity, 1.39 + capacity(), max_capacity(), used()); 1.40 } 1.41 } 1.42 1.43 @@ -92,31 +91,29 @@ 1.44 if (UsePerfData) { 1.45 assert(_perf_counters != NULL, "Should be initialized"); 1.46 1.47 - size_t capacity = calculate_capacity(); 1.48 - size_t max_capacity = MetaspaceAux::reserved_bytes(); 1.49 - size_t used = MetaspaceAux::allocated_used_bytes(); 1.50 - 1.51 - _perf_counters->update(capacity, max_capacity, used); 1.52 + _perf_counters->update(capacity(), max_capacity(), used()); 1.53 } 1.54 } 1.55 1.56 MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL; 1.57 1.58 -size_t CompressedClassSpaceCounters::calculate_capacity() { 1.59 - return MetaspaceAux::allocated_capacity_bytes(_class_type) + 1.60 - MetaspaceAux::free_bytes(_class_type) + 1.61 - MetaspaceAux::free_chunks_total_bytes(_class_type); 1.62 +size_t CompressedClassSpaceCounters::used() { 1.63 + return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); 1.64 +} 1.65 + 1.66 +size_t CompressedClassSpaceCounters::capacity() { 1.67 + return MetaspaceAux::committed_bytes(Metaspace::ClassType); 1.68 +} 1.69 + 1.70 +size_t CompressedClassSpaceCounters::max_capacity() { 1.71 + return MetaspaceAux::reserved_bytes(Metaspace::ClassType); 1.72 } 1.73 1.74 void CompressedClassSpaceCounters::update_performance_counters() { 1.75 if (UsePerfData && UseCompressedClassPointers) { 1.76 assert(_perf_counters != NULL, "Should be initialized"); 1.77 1.78 - size_t capacity = calculate_capacity(); 1.79 - size_t max_capacity = MetaspaceAux::reserved_bytes(_class_type); 1.80 - size_t used = MetaspaceAux::allocated_used_bytes(_class_type); 1.81 - 1.82 - _perf_counters->update(capacity, max_capacity, used); 1.83 + _perf_counters->update(capacity(), max_capacity(), used()); 1.84 } 1.85 } 1.86 1.87 @@ -126,12 +123,9 @@ 1.88 const char* ns = "compressedclassspace"; 1.89 1.90 if (UseCompressedClassPointers) { 1.91 - size_t min_capacity = MetaspaceAux::min_chunk_size_bytes(); 1.92 - size_t capacity = calculate_capacity(); 1.93 - size_t max_capacity = MetaspaceAux::reserved_bytes(_class_type); 1.94 - size_t used = MetaspaceAux::allocated_used_bytes(_class_type); 1.95 - 1.96 - _perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity, max_capacity, used); 1.97 + size_t min_capacity = 0; 1.98 + _perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity(), 1.99 + max_capacity(), used()); 1.100 } else { 1.101 _perf_counters = new MetaspacePerfCounters(ns, 0, 0, 0, 0); 1.102 }
2.1 --- a/src/share/vm/memory/metaspaceCounters.hpp Wed Sep 18 00:08:00 2013 +0000 2.2 +++ b/src/share/vm/memory/metaspaceCounters.hpp Tue Sep 17 20:59:07 2013 +0200 2.3 @@ -25,13 +25,15 @@ 2.4 #ifndef SHARE_VM_MEMORY_METASPACECOUNTERS_HPP 2.5 #define SHARE_VM_MEMORY_METASPACECOUNTERS_HPP 2.6 2.7 -#include "memory/metaspace.hpp" 2.8 +#include "memory/allocation.hpp" 2.9 2.10 class MetaspacePerfCounters; 2.11 2.12 class MetaspaceCounters: public AllStatic { 2.13 static MetaspacePerfCounters* _perf_counters; 2.14 - static size_t calculate_capacity(); 2.15 + static size_t used(); 2.16 + static size_t capacity(); 2.17 + static size_t max_capacity(); 2.18 2.19 public: 2.20 static void initialize_performance_counters(); 2.21 @@ -40,8 +42,9 @@ 2.22 2.23 class CompressedClassSpaceCounters: public AllStatic { 2.24 static MetaspacePerfCounters* _perf_counters; 2.25 - static size_t calculate_capacity(); 2.26 - static const Metaspace::MetadataType _class_type = Metaspace::ClassType; 2.27 + static size_t used(); 2.28 + static size_t capacity(); 2.29 + static size_t max_capacity(); 2.30 2.31 public: 2.32 static void initialize_performance_counters();
3.1 --- a/src/share/vm/services/memoryPool.cpp Wed Sep 18 00:08:00 2013 +0000 3.2 +++ b/src/share/vm/services/memoryPool.cpp Tue Sep 17 20:59:07 2013 +0200 3.3 @@ -260,10 +260,10 @@ 3.4 } 3.5 3.6 MetaspacePool::MetaspacePool() : 3.7 - MemoryPool("Metaspace", NonHeap, capacity_in_bytes(), calculate_max_size(), true, false) { } 3.8 + MemoryPool("Metaspace", NonHeap, 0, calculate_max_size(), true, false) { } 3.9 3.10 MemoryUsage MetaspacePool::get_memory_usage() { 3.11 - size_t committed = align_size_down_(capacity_in_bytes(), os::vm_page_size()); 3.12 + size_t committed = MetaspaceAux::committed_bytes(); 3.13 return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); 3.14 } 3.15 3.16 @@ -271,26 +271,19 @@ 3.17 return MetaspaceAux::allocated_used_bytes(); 3.18 } 3.19 3.20 -size_t MetaspacePool::capacity_in_bytes() const { 3.21 - return MetaspaceAux::allocated_capacity_bytes(); 3.22 -} 3.23 - 3.24 size_t MetaspacePool::calculate_max_size() const { 3.25 - return FLAG_IS_CMDLINE(MaxMetaspaceSize) ? MaxMetaspaceSize : max_uintx; 3.26 + return FLAG_IS_CMDLINE(MaxMetaspaceSize) ? MaxMetaspaceSize : 3.27 + MemoryUsage::undefined_size(); 3.28 } 3.29 3.30 CompressedKlassSpacePool::CompressedKlassSpacePool() : 3.31 - MemoryPool("Compressed Class Space", NonHeap, capacity_in_bytes(), CompressedClassSpaceSize, true, false) { } 3.32 + MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { } 3.33 3.34 size_t CompressedKlassSpacePool::used_in_bytes() { 3.35 return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); 3.36 } 3.37 3.38 -size_t CompressedKlassSpacePool::capacity_in_bytes() const { 3.39 - return MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); 3.40 -} 3.41 - 3.42 MemoryUsage CompressedKlassSpacePool::get_memory_usage() { 3.43 - size_t committed = align_size_down_(capacity_in_bytes(), os::vm_page_size()); 3.44 + size_t committed = MetaspaceAux::committed_bytes(Metaspace::ClassType); 3.45 return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); 3.46 }
4.1 --- a/src/share/vm/services/memoryPool.hpp Wed Sep 18 00:08:00 2013 +0000 4.2 +++ b/src/share/vm/services/memoryPool.hpp Tue Sep 17 20:59:07 2013 +0200 4.3 @@ -224,7 +224,6 @@ 4.4 4.5 class MetaspacePool : public MemoryPool { 4.6 size_t calculate_max_size() const; 4.7 - size_t capacity_in_bytes() const; 4.8 public: 4.9 MetaspacePool(); 4.10 MemoryUsage get_memory_usage(); 4.11 @@ -232,7 +231,6 @@ 4.12 }; 4.13 4.14 class CompressedKlassSpacePool : public MemoryPool { 4.15 - size_t capacity_in_bytes() const; 4.16 public: 4.17 CompressedKlassSpacePool(); 4.18 MemoryUsage get_memory_usage();
5.1 --- a/src/share/vm/services/memoryUsage.hpp Wed Sep 18 00:08:00 2013 +0000 5.2 +++ b/src/share/vm/services/memoryUsage.hpp Tue Sep 17 20:59:07 2013 +0200 5.3 @@ -63,10 +63,12 @@ 5.4 size_t committed() const { return _committed; } 5.5 size_t max_size() const { return _maxSize; } 5.6 5.7 + static size_t undefined_size() { return (size_t) -1; } 5.8 + 5.9 inline static jlong convert_to_jlong(size_t val) { 5.10 // In the 64-bit vm, a size_t can overflow a jlong (which is signed). 5.11 jlong ret; 5.12 - if (val == (size_t)-1) { 5.13 + if (val == undefined_size()) { 5.14 ret = -1L; 5.15 } else { 5.16 NOT_LP64(ret = val;)
6.1 --- a/test/gc/metaspace/TestMetaspaceMemoryPool.java Wed Sep 18 00:08:00 2013 +0000 6.2 +++ b/test/gc/metaspace/TestMetaspaceMemoryPool.java Tue Sep 17 20:59:07 2013 +0200 6.3 @@ -22,18 +22,15 @@ 6.4 */ 6.5 6.6 import java.util.List; 6.7 -import java.lang.management.ManagementFactory; 6.8 -import java.lang.management.MemoryManagerMXBean; 6.9 -import java.lang.management.MemoryPoolMXBean; 6.10 -import java.lang.management.MemoryUsage; 6.11 - 6.12 -import java.lang.management.RuntimeMXBean; 6.13 -import java.lang.management.ManagementFactory; 6.14 +import java.lang.management.*; 6.15 +import com.oracle.java.testlibrary.*; 6.16 +import static com.oracle.java.testlibrary.Asserts.*; 6.17 6.18 /* @test TestMetaspaceMemoryPool 6.19 * @bug 8000754 6.20 * @summary Tests that a MemoryPoolMXBeans is created for metaspace and that a 6.21 * MemoryManagerMXBean is created. 6.22 + * @library /testlibrary 6.23 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops TestMetaspaceMemoryPool 6.24 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:MaxMetaspaceSize=60m TestMetaspaceMemoryPool 6.25 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers TestMetaspaceMemoryPool 6.26 @@ -42,35 +39,18 @@ 6.27 public class TestMetaspaceMemoryPool { 6.28 public static void main(String[] args) { 6.29 verifyThatMetaspaceMemoryManagerExists(); 6.30 - verifyMemoryPool(getMemoryPool("Metaspace"), isFlagDefined("MaxMetaspaceSize")); 6.31 6.32 - if (runsOn64bit()) { 6.33 - if (usesCompressedOops()) { 6.34 + boolean isMetaspaceMaxDefined = InputArguments.containsPrefix("-XX:MaxMetaspaceSize"); 6.35 + verifyMemoryPool(getMemoryPool("Metaspace"), isMetaspaceMaxDefined); 6.36 + 6.37 + if (Platform.is64bit()) { 6.38 + if (InputArguments.contains("-XX:+UseCompressedOops")) { 6.39 MemoryPoolMXBean cksPool = getMemoryPool("Compressed Class Space"); 6.40 verifyMemoryPool(cksPool, true); 6.41 } 6.42 } 6.43 } 6.44 6.45 - private static boolean runsOn64bit() { 6.46 - return !System.getProperty("sun.arch.data.model").equals("32"); 6.47 - } 6.48 - 6.49 - private static boolean usesCompressedOops() { 6.50 - return isFlagDefined("+UseCompressedOops"); 6.51 - } 6.52 - 6.53 - private static boolean isFlagDefined(String name) { 6.54 - RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); 6.55 - List<String> args = runtimeMxBean.getInputArguments(); 6.56 - for (String arg : args) { 6.57 - if (arg.startsWith("-XX:" + name)) { 6.58 - return true; 6.59 - } 6.60 - } 6.61 - return false; 6.62 - } 6.63 - 6.64 private static void verifyThatMetaspaceMemoryManagerExists() { 6.65 List<MemoryManagerMXBean> managers = ManagementFactory.getMemoryManagerMXBeans(); 6.66 for (MemoryManagerMXBean manager : managers) { 6.67 @@ -95,32 +75,19 @@ 6.68 6.69 private static void verifyMemoryPool(MemoryPoolMXBean pool, boolean isMaxDefined) { 6.70 MemoryUsage mu = pool.getUsage(); 6.71 - assertDefined(mu.getInit(), "init"); 6.72 - assertDefined(mu.getUsed(), "used"); 6.73 - assertDefined(mu.getCommitted(), "committed"); 6.74 + long init = mu.getInit(); 6.75 + long used = mu.getUsed(); 6.76 + long committed = mu.getCommitted(); 6.77 + long max = mu.getMax(); 6.78 + 6.79 + assertGTE(init, 0L); 6.80 + assertGTE(used, init); 6.81 + assertGTE(committed, used); 6.82 6.83 if (isMaxDefined) { 6.84 - assertDefined(mu.getMax(), "max"); 6.85 + assertGTE(max, committed); 6.86 } else { 6.87 - assertUndefined(mu.getMax(), "max"); 6.88 - } 6.89 - } 6.90 - 6.91 - private static void assertDefined(long value, String name) { 6.92 - assertTrue(value != -1, "Expected " + name + " to be defined"); 6.93 - } 6.94 - 6.95 - private static void assertUndefined(long value, String name) { 6.96 - assertEquals(value, -1, "Expected " + name + " to be undefined"); 6.97 - } 6.98 - 6.99 - private static void assertEquals(long actual, long expected, String msg) { 6.100 - assertTrue(actual == expected, msg); 6.101 - } 6.102 - 6.103 - private static void assertTrue(boolean condition, String msg) { 6.104 - if (!condition) { 6.105 - throw new RuntimeException(msg); 6.106 + assertEQ(max, -1L); 6.107 } 6.108 } 6.109 }
7.1 --- a/test/gc/metaspace/TestMetaspacePerfCounters.java Wed Sep 18 00:08:00 2013 +0000 7.2 +++ b/test/gc/metaspace/TestMetaspacePerfCounters.java Tue Sep 17 20:59:07 2013 +0200 7.3 @@ -61,10 +61,15 @@ 7.4 } 7.5 7.6 private static void checkPerfCounters(String ns) throws Exception { 7.7 - for (PerfCounter counter : countersInNamespace(ns)) { 7.8 - String msg = "Expected " + counter.getName() + " to be larger than 0"; 7.9 - assertGT(counter.longValue(), 0L, msg); 7.10 - } 7.11 + long minCapacity = getMinCapacity(ns); 7.12 + long maxCapacity = getMaxCapacity(ns); 7.13 + long capacity = getCapacity(ns); 7.14 + long used = getUsed(ns); 7.15 + 7.16 + assertGTE(minCapacity, 0L); 7.17 + assertGTE(used, minCapacity); 7.18 + assertGTE(capacity, used); 7.19 + assertGTE(maxCapacity, capacity); 7.20 } 7.21 7.22 private static void checkEmptyPerfCounters(String ns) throws Exception { 7.23 @@ -75,12 +80,10 @@ 7.24 } 7.25 7.26 private static void checkUsedIncreasesWhenLoadingClass(String ns) throws Exception { 7.27 - PerfCounter used = PerfCounters.findByName(ns + ".used"); 7.28 - 7.29 - long before = used.longValue(); 7.30 + long before = getUsed(ns); 7.31 fooClass = compileAndLoad("Foo", "public class Foo { }"); 7.32 System.gc(); 7.33 - long after = used.longValue(); 7.34 + long after = getUsed(ns); 7.35 7.36 assertGT(after, before); 7.37 } 7.38 @@ -101,4 +104,20 @@ 7.39 private static boolean isUsingCompressedClassPointers() { 7.40 return Platform.is64bit() && InputArguments.contains("-XX:+UseCompressedClassPointers"); 7.41 } 7.42 + 7.43 + private static long getMinCapacity(String ns) throws Exception { 7.44 + return PerfCounters.findByName(ns + ".minCapacity").longValue(); 7.45 + } 7.46 + 7.47 + private static long getCapacity(String ns) throws Exception { 7.48 + return PerfCounters.findByName(ns + ".capacity").longValue(); 7.49 + } 7.50 + 7.51 + private static long getMaxCapacity(String ns) throws Exception { 7.52 + return PerfCounters.findByName(ns + ".maxCapacity").longValue(); 7.53 + } 7.54 + 7.55 + private static long getUsed(String ns) throws Exception { 7.56 + return PerfCounters.findByName(ns + ".used").longValue(); 7.57 + } 7.58 }
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Tue Sep 17 20:59:07 2013 +0200 8.3 @@ -0,0 +1,86 @@ 8.4 +/* 8.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +import java.util.List; 8.28 +import java.lang.management.*; 8.29 + 8.30 +import com.oracle.java.testlibrary.*; 8.31 +import static com.oracle.java.testlibrary.Asserts.*; 8.32 + 8.33 +/* @test TestPerfCountersAndMemoryPools 8.34 + * @bug 8023476 8.35 + * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace 8.36 + * report the same data. 8.37 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools 8.38 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools 8.39 + */ 8.40 +public class TestPerfCountersAndMemoryPools { 8.41 + public static void main(String[] args) throws Exception { 8.42 + checkMemoryUsage("Metaspace", "sun.gc.metaspace"); 8.43 + 8.44 + if (InputArguments.contains("-XX:+UseCompressedKlassPointers") && Platform.is64bit()) { 8.45 + checkMemoryUsage("Compressed Class Space", "sun.gc.compressedclassspace"); 8.46 + } 8.47 + } 8.48 + 8.49 + private static MemoryUsage getMemoryUsage(String memoryPoolName) { 8.50 + List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans(); 8.51 + for (MemoryPoolMXBean pool : pools) { 8.52 + if (pool.getName().equals(memoryPoolName)) { 8.53 + return pool.getUsage(); 8.54 + } 8.55 + } 8.56 + 8.57 + throw new RuntimeException("Excpted to find a memory pool with name " + 8.58 + memoryPoolName); 8.59 + } 8.60 + 8.61 + private static void checkMemoryUsage(String memoryPoolName, String perfNS) 8.62 + throws Exception { 8.63 + // Need to do a gc before each comparison to update the perf counters 8.64 + 8.65 + System.gc(); 8.66 + MemoryUsage mu = getMemoryUsage(memoryPoolName); 8.67 + assertEQ(getMinCapacity(perfNS), mu.getInit()); 8.68 + 8.69 + System.gc(); 8.70 + mu = getMemoryUsage(memoryPoolName); 8.71 + assertEQ(getUsed(perfNS), mu.getUsed()); 8.72 + 8.73 + System.gc(); 8.74 + mu = getMemoryUsage(memoryPoolName); 8.75 + assertEQ(getCapacity(perfNS), mu.getCommitted()); 8.76 + } 8.77 + 8.78 + private static long getMinCapacity(String ns) throws Exception { 8.79 + return PerfCounters.findByName(ns + ".minCapacity").longValue(); 8.80 + } 8.81 + 8.82 + private static long getCapacity(String ns) throws Exception { 8.83 + return PerfCounters.findByName(ns + ".capacity").longValue(); 8.84 + } 8.85 + 8.86 + private static long getUsed(String ns) throws Exception { 8.87 + return PerfCounters.findByName(ns + ".used").longValue(); 8.88 + } 8.89 +}
9.1 --- a/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java Wed Sep 18 00:08:00 2013 +0000 9.2 +++ b/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java Tue Sep 17 20:59:07 2013 +0200 9.3 @@ -41,6 +41,9 @@ 9.4 /** 9.5 * Returns true if {@code arg} is an input argument to the VM. 9.6 * 9.7 + * This is useful for checking boolean flags such as -XX:+UseSerialGC or 9.8 + * -XX:-UsePerfData. 9.9 + * 9.10 * @param arg The name of the argument. 9.11 * @return {@code true} if the given argument is an input argument, 9.12 * otherwise {@code false}. 9.13 @@ -48,4 +51,26 @@ 9.14 public static boolean contains(String arg) { 9.15 return args.contains(arg); 9.16 } 9.17 + 9.18 + /** 9.19 + * Returns true if {@code prefix} is the start of an input argument to the 9.20 + * VM. 9.21 + * 9.22 + * This is useful for checking if flags describing a quantity, such as 9.23 + * -XX:+MaxMetaspaceSize=100m, is set without having to know the quantity. 9.24 + * To check if the flag -XX:MaxMetaspaceSize is set, use 9.25 + * {@code InputArguments.containsPrefix("-XX:MaxMetaspaceSize")}. 9.26 + * 9.27 + * @param prefix The start of the argument. 9.28 + * @return {@code true} if the given argument is the start of an input 9.29 + * argument, otherwise {@code false}. 9.30 + */ 9.31 + public static boolean containsPrefix(String prefix) { 9.32 + for (String arg : args) { 9.33 + if (arg.startsWith(prefix)) { 9.34 + return true; 9.35 + } 9.36 + } 9.37 + return false; 9.38 + } 9.39 }