--- old/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp 2013-09-12 16:59:17.000000000 +0200 +++ new/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp 2013-09-12 16:59:17.000000000 +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 --- /dev/null 2013-08-08 14:59:45.482829247 +0200 +++ new/test/gc/metaspace/TestMetaspaceSizeFlags.java 2013-09-12 16:59:17.000000000 +0200 @@ -0,0 +1,100 @@ +/* + * 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); + } + + 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 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; + } + } +} --- old/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java 2013-09-12 16:59:17.000000000 +0200 +++ new/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java 2013-09-12 16:59:17.000000000 +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"); } } @@ -252,6 +252,37 @@ + "' found in stderr \n"); } } + + /** + * Get the captured group of the first string matching the pattern. + * stdout is searched before stderr. + * + * @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 stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. + * stdout is searched before stderr. + * + * @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 --- old/src/share/vm/memory/collectorPolicy.cpp 2013-09-12 16:59:17.000000000 +0200 +++ new/src/share/vm/memory/collectorPolicy.cpp 2013-09-12 16:59:17.000000000 +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())); + } + + if (!FLAG_IS_DEFAULT(MaxMetaspaceSize)) { + if (MetaspaceSize > MaxMetaspaceSize) { + FLAG_SET_ERGO(uintx, MetaspaceSize, MaxMetaspaceSize); + } } - 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; + + if (!is_size_aligned(MetaspaceSize, min_alignment())) { + FLAG_SET_ERGO(uintx, MetaspaceSize, + restricted_align_down(MetaspaceSize, min_alignment())); } - MinMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MinMetaspaceExpansion, min_alignment())); - MaxMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MaxMetaspaceExpansion, min_alignment())); + MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, min_alignment()); + MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, min_alignment()); MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, min_alignment());