8256450: Add gz option to jmap to write a gzipped heap dump
Reviewed-by: cjplummer, sspitsyn, phh
This commit is contained in:
parent
dee79d6053
commit
461c5fc637
@ -218,6 +218,7 @@ static jint jcmd(AttachOperation* op, outputStream* out) {
|
||||
// Input arguments :-
|
||||
// arg0: Name of the dump file
|
||||
// arg1: "-live" or "-all"
|
||||
// arg2: Compress level
|
||||
jint dump_heap(AttachOperation* op, outputStream* out) {
|
||||
const char* path = op->arg(0);
|
||||
if (path == NULL || path[0] == '\0') {
|
||||
@ -233,11 +234,22 @@ jint dump_heap(AttachOperation* op, outputStream* out) {
|
||||
live_objects_only = strcmp(arg1, "-live") == 0;
|
||||
}
|
||||
|
||||
const char* num_str = op->arg(2);
|
||||
uintx level = 0;
|
||||
if (num_str != NULL && num_str[0] != '\0') {
|
||||
if (!Arguments::parse_uintx(num_str, &level, 0)) {
|
||||
out->print_cr("Invalid compress level: [%s]", num_str);
|
||||
return JNI_ERR;
|
||||
} else if (level < 1 || level > 9) {
|
||||
out->print_cr("Compression level out of range (1-9): " UINTX_FORMAT, level);
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
// Request a full GC before heap dump if live_objects_only = true
|
||||
// This helps reduces the amount of unreachable objects in the dump
|
||||
// and makes it easier to browse.
|
||||
HeapDumper dumper(live_objects_only /* request GC */);
|
||||
dumper.dump(op->arg(0), out);
|
||||
dumper.dump(op->arg(0), out, (int)level);
|
||||
}
|
||||
return JNI_OK;
|
||||
}
|
||||
|
@ -209,6 +209,7 @@ public class JMap {
|
||||
String subopts[] = options.split(",");
|
||||
String filename = null;
|
||||
String liveopt = "-all";
|
||||
String compress_level = null;
|
||||
|
||||
for (int i = 0; i < subopts.length; i++) {
|
||||
String subopt = subopts[i];
|
||||
@ -224,6 +225,12 @@ public class JMap {
|
||||
}
|
||||
} else if (subopt.equals("format=b")) {
|
||||
// ignore format (not needed at this time)
|
||||
} else if (subopt.startsWith("gz=")) {
|
||||
compress_level = subopt.substring("gz=".length());
|
||||
if (compress_level == null) {
|
||||
System.err.println("Fail: no number provided in option: '" + subopt + "'");
|
||||
usage(1);
|
||||
}
|
||||
} else {
|
||||
System.err.println("Fail: invalid option: '" + subopt + "'");
|
||||
usage(1);
|
||||
@ -238,7 +245,7 @@ public class JMap {
|
||||
System.out.flush();
|
||||
|
||||
// dumpHeap is not the same as jcmd GC.heap_dump
|
||||
executeCommandForPid(pid, "dumpheap", filename, liveopt);
|
||||
executeCommandForPid(pid, "dumpheap", filename, liveopt, compress_level);
|
||||
}
|
||||
|
||||
private static void checkForUnsupportedOptions(String[] args) {
|
||||
@ -303,6 +310,8 @@ public class JMap {
|
||||
System.err.println(" all dump all objects in the heap (default if one of \"live\" or \"all\" is not specified)");
|
||||
System.err.println(" format=b binary format");
|
||||
System.err.println(" file=<file> dump heap to <file>");
|
||||
System.err.println(" gz=<number> If specified, the heap dump is written in gzipped format using the given compression level.");
|
||||
System.err.println(" 1 (recommended) is the fastest, 9 the strongest compression.");
|
||||
System.err.println("");
|
||||
System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>");
|
||||
System.err.println("");
|
||||
|
@ -22,10 +22,13 @@
|
||||
*/
|
||||
|
||||
import static jdk.test.lib.Asserts.assertTrue;
|
||||
import static jdk.test.lib.Asserts.assertFalse;
|
||||
import static jdk.test.lib.Asserts.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.Utils;
|
||||
@ -114,6 +117,7 @@ public class BasicJMapTest {
|
||||
testDump();
|
||||
testDumpLive();
|
||||
testDumpAll();
|
||||
testDumpCompressed();
|
||||
}
|
||||
|
||||
private static void testHisto() throws Exception {
|
||||
@ -211,20 +215,25 @@ public class BasicJMapTest {
|
||||
}
|
||||
|
||||
private static void testDump() throws Exception {
|
||||
dump(false, false);
|
||||
dump(false, false, false);
|
||||
}
|
||||
|
||||
private static void testDumpLive() throws Exception {
|
||||
dump(true, false);
|
||||
dump(true, false, false);
|
||||
}
|
||||
|
||||
private static void testDumpAll() throws Exception {
|
||||
dump(false, true);
|
||||
dump(false, true, false);
|
||||
}
|
||||
|
||||
private static void dump(boolean live, boolean explicitAll) throws Exception {
|
||||
private static void testDumpCompressed() throws Exception {
|
||||
dump(true, false, true);
|
||||
}
|
||||
|
||||
private static void dump(boolean live, boolean explicitAll, boolean compressed) throws Exception {
|
||||
String liveArg = "";
|
||||
String fileArg = "";
|
||||
String compressArg = "";
|
||||
String allArgs = "-dump:";
|
||||
|
||||
if (live && explicitAll) {
|
||||
@ -237,14 +246,20 @@ public class BasicJMapTest {
|
||||
liveArg = "all,";
|
||||
}
|
||||
|
||||
File file = new File("jmap.dump" + System.currentTimeMillis() + ".hprof");
|
||||
String filePath = "jmap.dump" + System.currentTimeMillis() + ".hprof";
|
||||
if (compressed) {
|
||||
compressArg = "gz=1,";
|
||||
filePath = filePath + ".gz";
|
||||
}
|
||||
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
fileArg = "file=" + file.getName();
|
||||
|
||||
OutputAnalyzer output;
|
||||
allArgs = allArgs + liveArg + "format=b," + fileArg;
|
||||
allArgs = allArgs + liveArg + compressArg + "format=b," + fileArg;
|
||||
output = jmap(allArgs);
|
||||
output.shouldHaveExitValue(0);
|
||||
output.shouldContain("Heap dump file created");
|
||||
@ -255,7 +270,18 @@ public class BasicJMapTest {
|
||||
private static void verifyDumpFile(File dump) {
|
||||
assertTrue(dump.exists() && dump.isFile(), "Could not create dump file " + dump.getAbsolutePath());
|
||||
try {
|
||||
HprofParser.parse(dump);
|
||||
File out = HprofParser.parse(dump);
|
||||
|
||||
assertTrue(out != null && out.exists() && out.isFile(),
|
||||
"Could not find hprof parser output file");
|
||||
List<String> lines = Files.readAllLines(out.toPath());
|
||||
assertTrue(lines.size() > 0, "hprof parser output file is empty");
|
||||
for (String line : lines) {
|
||||
assertFalse(line.matches(".*WARNING(?!.*Failed to resolve " +
|
||||
"object.*constantPoolOop.*).*"));
|
||||
}
|
||||
|
||||
out.delete();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Could not parse dump file " + dump.getAbsolutePath());
|
||||
|
Loading…
Reference in New Issue
Block a user