8024650: Don't adjust MaxMetaspaceSize up to MetaspaceSize
Reviewed-by: jwilhelm, brutisso, tschatzl
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Fri Sep 13 22:21:06 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Fri Sep 13 22:22:14 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,9 +68,6 @@
size_t min_old_gen_size() { return _min_gen1_size; }
size_t old_gen_size() { return _initial_gen1_size; }
size_t max_old_gen_size() { return _max_gen1_size; }
-
- size_t metaspace_size() { return MetaspaceSize; }
- size_t max_metaspace_size() { return MaxMetaspaceSize; }
};
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GENERATIONSIZER_HPP
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Sep 13 22:21:06 2013 +0200
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Sep 13 22:22:14 2013 +0200
@@ -47,6 +47,11 @@
// CollectorPolicy methods.
+// Align down. If the aligning result in 0, return 'alignment'.
+static size_t restricted_align_down(size_t size, size_t alignment) {
+ return MAX2(alignment, align_size_down_(size, alignment));
+}
+
void CollectorPolicy::initialize_flags() {
assert(max_alignment() >= min_alignment(),
err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT,
@@ -59,18 +64,24 @@
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
}
- if (MetaspaceSize > MaxMetaspaceSize) {
- MaxMetaspaceSize = MetaspaceSize;
+ if (!is_size_aligned(MaxMetaspaceSize, max_alignment())) {
+ FLAG_SET_ERGO(uintx, MaxMetaspaceSize,
+ restricted_align_down(MaxMetaspaceSize, max_alignment()));
}
- MetaspaceSize = MAX2(min_alignment(), align_size_down_(MetaspaceSize, min_alignment()));
- // Don't increase Metaspace size limit above specified.
- MaxMetaspaceSize = align_size_down(MaxMetaspaceSize, max_alignment());
+
if (MetaspaceSize > MaxMetaspaceSize) {
- MetaspaceSize = MaxMetaspaceSize;
+ FLAG_SET_ERGO(uintx, MetaspaceSize, MaxMetaspaceSize);
}
- MinMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MinMetaspaceExpansion, min_alignment()));
- MaxMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MaxMetaspaceExpansion, min_alignment()));
+ if (!is_size_aligned(MetaspaceSize, min_alignment())) {
+ FLAG_SET_ERGO(uintx, MetaspaceSize,
+ restricted_align_down(MetaspaceSize, min_alignment()));
+ }
+
+ assert(MetaspaceSize <= MaxMetaspaceSize, "Must be");
+
+ MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, min_alignment());
+ MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, min_alignment());
MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, min_alignment());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java Fri Sep 13 22:22:14 2013 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+/*
+ * @test TestMetaspaceSizeFlags
+ * @key gc
+ * @bug 8024650
+ * @summary Test that metaspace size flags can be set correctly
+ * @library /testlibrary
+ */
+public class TestMetaspaceSizeFlags {
+ public static final long K = 1024L;
+ public static final long M = 1024L * K;
+
+ // HotSpot uses a number of different values to align memory size flags.
+ // This is currently the largest alignment (unless huge large pages are used).
+ public static final long MAX_ALIGNMENT = 32 * M;
+
+ public static void main(String [] args) throws Exception {
+ testMaxMetaspaceSizeEQMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT);
+ // 8024650: MaxMetaspaceSize was adjusted instead of MetaspaceSize.
+ testMaxMetaspaceSizeLTMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT * 2);
+ testMaxMetaspaceSizeGTMetaspaceSize(MAX_ALIGNMENT * 2, MAX_ALIGNMENT);
+ testTooSmallInitialMetaspace(0, 0);
+ testTooSmallInitialMetaspace(0, MAX_ALIGNMENT);
+ testTooSmallInitialMetaspace(MAX_ALIGNMENT, 0);
+ }
+
+ private static void testMaxMetaspaceSizeEQMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize);
+ Asserts.assertEQ(maxMetaspaceSize, metaspaceSize);
+ Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize);
+ Asserts.assertEQ(mf.metaspaceSize, metaspaceSize);
+ }
+
+ private static void testMaxMetaspaceSizeLTMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize);
+ Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize);
+ Asserts.assertEQ(mf.metaspaceSize, maxMetaspaceSize);
+ }
+
+ private static void testMaxMetaspaceSizeGTMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize);
+ Asserts.assertGT(maxMetaspaceSize, metaspaceSize);
+ Asserts.assertGT(mf.maxMetaspaceSize, mf.metaspaceSize);
+ Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize);
+ Asserts.assertEQ(mf.metaspaceSize, metaspaceSize);
+ }
+
+ private static void testTooSmallInitialMetaspace(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
+ output.shouldContain("Too small initial Metaspace size");
+ }
+
+ private static MetaspaceFlags runAndGetValue(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
+ output.shouldNotMatch("Error occurred during initialization of VM\n.*");
+
+ String stringMaxMetaspaceSize = output.firstMatch(".* MaxMetaspaceSize .* := (\\d+).*", 1);
+ String stringMetaspaceSize = output.firstMatch(".* MetaspaceSize .* := (\\d+).*", 1);
+
+ return new MetaspaceFlags(Long.parseLong(stringMaxMetaspaceSize),
+ Long.parseLong(stringMetaspaceSize));
+ }
+
+ private static OutputAnalyzer run(long maxMetaspaceSize, long metaspaceSize) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:MaxMetaspaceSize=" + maxMetaspaceSize,
+ "-XX:MetaspaceSize=" + metaspaceSize,
+ "-XX:-UseLargePages", // Prevent us from using 2GB large pages on solaris + sparc.
+ "-XX:+PrintFlagsFinal",
+ "-version");
+ return new OutputAnalyzer(pb.start());
+ }
+
+ private static class MetaspaceFlags {
+ public long maxMetaspaceSize;
+ public long metaspaceSize;
+ public MetaspaceFlags(long maxMetaspaceSize, long metaspaceSize) {
+ this.maxMetaspaceSize = maxMetaspaceSize;
+ this.metaspaceSize = metaspaceSize;
+ }
+ }
+}
--- a/hotspot/test/testlibrary/OutputAnalyzerTest.java Fri Sep 13 22:21:06 2013 +0200
+++ b/hotspot/test/testlibrary/OutputAnalyzerTest.java Fri Sep 13 22:22:14 2013 +0200
@@ -172,5 +172,22 @@
} catch (RuntimeException e) {
// expected
}
+
+ {
+ String aaaa = "aaaa";
+ String result = output.firstMatch(aaaa);
+ if (!aaaa.equals(result)) {
+ throw new Exception("firstMatch(String) faild to match. Expected: " + aaaa + " got: " + result);
+ }
+ }
+
+ {
+ String aa = "aa";
+ String aa_grouped_aa = aa + "(" + aa + ")";
+ String result = output.firstMatch(aa_grouped_aa, 1);
+ if (!aa.equals(result)) {
+ throw new Exception("firstMatch(String, int) failed to match. Expected: " + aa + " got: " + result);
+ }
+ }
}
}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Fri Sep 13 22:21:06 2013 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Fri Sep 13 22:22:14 2013 +0200
@@ -211,13 +211,13 @@
if (matcher.find()) {
reportDiagnosticSummary();
throw new RuntimeException("'" + pattern
- + "' found in stdout \n");
+ + "' found in stdout: '" + matcher.group() + "' \n");
}
matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
if (matcher.find()) {
reportDiagnosticSummary();
throw new RuntimeException("'" + pattern
- + "' found in stderr \n");
+ + "' found in stderr: '" + matcher.group() + "' \n");
}
}
@@ -254,6 +254,37 @@
}
/**
+ * Get the captured group of the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @param group The group to capture
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern, int group) {
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (stderrMatcher.find()) {
+ return stderrMatcher.group(group);
+ }
+ if (stdoutMatcher.find()) {
+ return stdoutMatcher.group(group);
+ }
+ return null;
+ }
+
+ /**
+ * Get the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern) {
+ return firstMatch(pattern, 0);
+ }
+
+ /**
* Verify the exit value of the process
*
* @param expectedExitValue Expected exit value from process