fa5cc4cc8e
Reviewed-by: kvn, shade
249 lines
12 KiB
Java
249 lines
12 KiB
Java
/*
|
|
* Copyright (c) 2022 SAP SE. All rights reserved.
|
|
* Copyright (c) 2022, 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.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* @test id=global-limit
|
|
* @summary Verify -XX:MallocLimit with a global limit
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest global-limit
|
|
*/
|
|
|
|
/*
|
|
* @test id=compiler-limit
|
|
* @summary Verify -XX:MallocLimit with a compiler-specific limit (for "mtCompiler" category)
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest compiler-limit
|
|
*/
|
|
|
|
/*
|
|
* @test id=multi-limit
|
|
* @summary Verify -XX:MallocLimit with multiple limits
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest multi-limit
|
|
*/
|
|
|
|
/*
|
|
* @test id=valid-settings
|
|
* @summary Verify -XX:MallocLimit rejects invalid settings
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest valid-settings
|
|
*/
|
|
|
|
/*
|
|
* @test id=invalid-settings
|
|
* @summary Verify -XX:MallocLimit rejects invalid settings
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest invalid-settings
|
|
*/
|
|
|
|
/*
|
|
* @test id=limit-without-nmt
|
|
* @summary Verify that the VM warns if -XX:MallocLimit is given but NMT is disabled
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib
|
|
* @run driver MallocLimitTest limit-without-nmt
|
|
*/
|
|
|
|
|
|
import jdk.test.lib.Asserts;
|
|
import jdk.test.lib.process.OutputAnalyzer;
|
|
import jdk.test.lib.process.ProcessTools;
|
|
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
public class MallocLimitTest {
|
|
|
|
private static ProcessBuilder processBuilderWithSetting(String... extraSettings) {
|
|
List<String> args = new ArrayList<>();
|
|
args.add("-XX:+UnlockDiagnosticVMOptions"); // MallocLimit is diagnostic
|
|
args.add("-Xmx64m");
|
|
args.add("-XX:-CreateCoredumpOnCrash");
|
|
args.add("-Xlog:nmt");
|
|
args.add("-XX:NativeMemoryTracking=summary");
|
|
args.addAll(Arrays.asList(extraSettings));
|
|
args.add("-version");
|
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
|
|
return pb;
|
|
}
|
|
|
|
private static void testGlobalLimit() throws IOException {
|
|
long smallMemorySize = 1024*1024; // 1m
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=" + smallMemorySize);
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.shouldNotHaveExitValue(0);
|
|
output.shouldContain("[nmt] MallocLimit: total limit: 1024K"); // printed by byte_size_in_proper_unit()
|
|
String s = output.firstMatch(".*MallocLimit: reached limit \\(size: (\\d+), limit: " + smallMemorySize + "\\).*", 1);
|
|
Asserts.assertNotNull(s);
|
|
long size = Long.parseLong(s);
|
|
Asserts.assertGreaterThan(size, smallMemorySize);
|
|
}
|
|
|
|
private static void testCompilerLimit() throws IOException {
|
|
// Here, we count on the VM, running with -Xcomp and with 1m of arena space allowed, will start a compilation
|
|
// and then trip over the limit.
|
|
// If limit is too small, Compiler stops too early and we won't get a Retry file (see below, we check that).
|
|
// If limit is too large, we may not trigger it for java -version.
|
|
// 1m seems to work out fine.
|
|
long smallMemorySize = 1024*1024; // 1m
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=compiler:" + smallMemorySize,
|
|
"-Xcomp" // make sure we hit the compiler category limit
|
|
);
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.shouldNotHaveExitValue(0);
|
|
output.shouldContain("[nmt] MallocLimit: category \"Compiler\" limit: 1024K"); // printed by byte_size_in_proper_unit
|
|
String s = output.firstMatch(".*MallocLimit: category \"Compiler\" reached limit \\(size: (\\d+), limit: " + smallMemorySize + "\\).*", 1);
|
|
Asserts.assertNotNull(s);
|
|
long size = Long.parseLong(s);
|
|
output.shouldContain("Compiler replay data is saved as");
|
|
Asserts.assertGreaterThan(size, smallMemorySize);
|
|
}
|
|
|
|
private static void testMultiLimit() throws IOException {
|
|
long smallMemorySize = 1024; // 1k
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=mtOther:2g,compiler:1g,internal:" + smallMemorySize);
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.shouldNotHaveExitValue(0);
|
|
output.shouldContain("[nmt] MallocLimit: category \"Compiler\" limit: 1024M");
|
|
output.shouldContain("[nmt] MallocLimit: category \"Internal\" limit: 1024B");
|
|
output.shouldContain("[nmt] MallocLimit: category \"Other\" limit: 2048M");
|
|
String s = output.firstMatch(".*MallocLimit: category \"Internal\" reached limit \\(size: (\\d+), limit: " + smallMemorySize + "\\).*", 1);
|
|
long size = Long.parseLong(s);
|
|
Asserts.assertGreaterThan(size, smallMemorySize);
|
|
}
|
|
|
|
private static void testValidSetting(String setting, String... expected_output) throws IOException {
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=" + setting);
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.shouldHaveExitValue(0);
|
|
for (String expected : expected_output) {
|
|
output.shouldContain(expected);
|
|
}
|
|
}
|
|
|
|
private static void testValidSettings() throws IOException {
|
|
// Test a number of valid settings.
|
|
testValidSetting(
|
|
"2097152k",
|
|
"[nmt] MallocLimit: total limit: 2048M",
|
|
"[nmt] NMT initialized: summary"
|
|
);
|
|
testValidSetting(
|
|
"gc:1234567891,mtInternal:987654321,Object Monitors:1g",
|
|
"[nmt] MallocLimit: category \"GC\" limit: 1177M",
|
|
"[nmt] MallocLimit: category \"Internal\" limit: 941M",
|
|
"[nmt] MallocLimit: category \"Object Monitors\" limit: 1024M",
|
|
"[nmt] NMT initialized: summary"
|
|
);
|
|
// Set all categories individually:
|
|
testValidSetting(
|
|
"JavaHeap:1024m,Class:1025m,Thread:1026m,ThreadStack:1027m,Code:1028m,GC:1029m,GCCardSet:1030m,Compiler:1031m,JVMCI:1032m," +
|
|
"Internal:1033m,Other:1034m,Symbol:1035m,NMT:1036m,ClassShared:1037m,Chunk:1038m,Test:1039m,Tracing:1040m,Logging:1041m," +
|
|
"Statistics:1042m,Arguments:1043m,Module:1044m,Safepoint:1045m,Synchronizer:1046m,Serviceability:1047m,Metaspace:1048m,StringDedup:1049m,ObjectMonitor:1050m",
|
|
"[nmt] MallocLimit: category \"Java Heap\" limit: 1024M",
|
|
"[nmt] MallocLimit: category \"Class\" limit: 1025M",
|
|
"[nmt] MallocLimit: category \"Thread\" limit: 1026M",
|
|
"[nmt] MallocLimit: category \"Thread Stack\" limit: 1027M",
|
|
"[nmt] MallocLimit: category \"Code\" limit: 1028M",
|
|
"[nmt] MallocLimit: category \"GC\" limit: 1029M",
|
|
"[nmt] MallocLimit: category \"GCCardSet\" limit: 1030M",
|
|
"[nmt] MallocLimit: category \"Compiler\" limit: 1031M",
|
|
"[nmt] MallocLimit: category \"JVMCI\" limit: 1032M",
|
|
"[nmt] MallocLimit: category \"Internal\" limit: 1033M",
|
|
"[nmt] MallocLimit: category \"Other\" limit: 1034M",
|
|
"[nmt] MallocLimit: category \"Symbol\" limit: 1035M",
|
|
"[nmt] MallocLimit: category \"Native Memory Tracking\" limit: 1036M",
|
|
"[nmt] MallocLimit: category \"Shared class space\" limit: 1037M",
|
|
"[nmt] MallocLimit: category \"Arena Chunk\" limit: 1038M",
|
|
"[nmt] MallocLimit: category \"Test\" limit: 1039M",
|
|
"[nmt] MallocLimit: category \"Tracing\" limit: 1040M",
|
|
"[nmt] MallocLimit: category \"Logging\" limit: 1041M",
|
|
"[nmt] MallocLimit: category \"Statistics\" limit: 1042M",
|
|
"[nmt] MallocLimit: category \"Arguments\" limit: 1043M",
|
|
"[nmt] MallocLimit: category \"Module\" limit: 1044M",
|
|
"[nmt] MallocLimit: category \"Safepoint\" limit: 1045M",
|
|
"[nmt] MallocLimit: category \"Synchronization\" limit: 1046M",
|
|
"[nmt] MallocLimit: category \"Serviceability\" limit: 1047M",
|
|
"[nmt] MallocLimit: category \"Metaspace\" limit: 1048M",
|
|
"[nmt] MallocLimit: category \"String Deduplication\" limit: 1049M",
|
|
"[nmt] MallocLimit: category \"Object Monitors\" limit: 1050M",
|
|
"[nmt] NMT initialized: summary"
|
|
);
|
|
}
|
|
|
|
private static void testInvalidSetting(String setting, String expected_error) throws IOException {
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:MallocLimit=" + setting);
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.reportDiagnosticSummary();
|
|
output.shouldNotHaveExitValue(0);
|
|
output.shouldContain(expected_error);
|
|
}
|
|
|
|
private static void testInvalidSettings() throws IOException {
|
|
// Test a number of invalid settings the parser should catch. VM should abort in initialization.
|
|
testInvalidSetting("gc", "MallocLimit: colon missing: gc");
|
|
testInvalidSetting("gc:abc", "Invalid MallocLimit size: abc");
|
|
testInvalidSetting("abcd:10m", "MallocLimit: invalid nmt category: abcd");
|
|
testInvalidSetting("nmt:100m,abcd:10m", "MallocLimit: invalid nmt category: abcd");
|
|
testInvalidSetting("0", "MallocLimit: limit must be > 0");
|
|
testInvalidSetting("GC:0", "MallocLimit: limit must be > 0");
|
|
}
|
|
|
|
private static void testLimitWithoutNmt() throws IOException {
|
|
ProcessBuilder pb = processBuilderWithSetting("-XX:NativeMemoryTracking=off", // overrides "summary" from processBuilderWithSetting()
|
|
"-XX:MallocLimit=3g");
|
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
output.reportDiagnosticSummary();
|
|
output.shouldHaveExitValue(0); // Not a fatal error, just a warning
|
|
output.shouldContain("MallocLimit will be ignored since NMT is disabled");
|
|
}
|
|
|
|
public static void main(String args[]) throws Exception {
|
|
|
|
if (args[0].equals("global-limit")) {
|
|
testGlobalLimit();
|
|
} else if (args[0].equals("compiler-limit")) {
|
|
testCompilerLimit();
|
|
} else if (args[0].equals("multi-limit")) {
|
|
testMultiLimit();
|
|
} else if (args[0].equals("valid-settings")) {
|
|
testValidSettings();
|
|
} else if (args[0].equals("invalid-settings")) {
|
|
testInvalidSettings();
|
|
} else if (args[0].equals("limit-without-nmt")) {
|
|
testLimitWithoutNmt();
|
|
} else {
|
|
throw new RuntimeException("invalid test: " + args[0]);
|
|
}
|
|
}
|
|
}
|