mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 02:24:40 +02:00
8259070: Add jcmd option to dump CDS
Reviewed-by: ccheung, iklam, mli
This commit is contained in:
parent
593194864a
commit
e7cbeba866
23 changed files with 800 additions and 75 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
|
@ -25,7 +25,15 @@
|
|||
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -63,6 +71,7 @@ public class CDS {
|
|||
public static boolean isSharingEnabled() {
|
||||
return isSharingEnabled;
|
||||
}
|
||||
|
||||
private static native boolean isDumpingClassList0();
|
||||
private static native boolean isDumpingArchive0();
|
||||
private static native boolean isSharingEnabled0();
|
||||
|
@ -195,4 +204,123 @@ public class CDS {
|
|||
};
|
||||
return retArray;
|
||||
}
|
||||
|
||||
private static native void dumpClassList(String listFileName);
|
||||
private static native void dumpDynamicArchive(String archiveFileName);
|
||||
|
||||
private static String drainOutput(InputStream stream, long pid, String tail, List<String> cmds) {
|
||||
String fileName = "java_pid" + pid + "_" + tail;
|
||||
new Thread( ()-> {
|
||||
try (InputStreamReader isr = new InputStreamReader(stream);
|
||||
BufferedReader rdr = new BufferedReader(isr);
|
||||
PrintStream prt = new PrintStream(fileName)) {
|
||||
prt.println("Command:");
|
||||
for (String s : cmds) {
|
||||
prt.print(s + " ");
|
||||
}
|
||||
prt.println("");
|
||||
String line;
|
||||
while((line = rdr.readLine()) != null) {
|
||||
prt.println(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("IOExeption happens during drain stream to file " +
|
||||
fileName + ": " + e.getMessage());
|
||||
}}).start();
|
||||
return fileName;
|
||||
}
|
||||
|
||||
private static String[] excludeFlags = {
|
||||
"-XX:DumpLoadedClassList=",
|
||||
"-XX:+DumpSharedSpaces",
|
||||
"-XX:+DynamicDumpSharedSpaces",
|
||||
"-XX:+RecordDynamicDumpInfo",
|
||||
"-Xshare:",
|
||||
"-XX:SharedClassListFile=",
|
||||
"-XX:SharedArchiveFile=",
|
||||
"-XX:ArchiveClassesAtExit=",
|
||||
"-XX:+UseSharedSpaces",
|
||||
"-XX:+RequireSharedSpaces"};
|
||||
private static boolean containsExcludedFlags(String testStr) {
|
||||
for (String e : excludeFlags) {
|
||||
if (testStr.contains(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* called from jcmd VM.cds to dump static or dynamic shared archive
|
||||
* @param isStatic true for dump static archive or false for dynnamic archive.
|
||||
* @param fileName user input archive name, can be null.
|
||||
*/
|
||||
private static void dumpSharedArchive(boolean isStatic, String fileName) throws Exception {
|
||||
String currentPid = String.valueOf(ProcessHandle.current().pid());
|
||||
String archiveFile = fileName != null ? fileName :
|
||||
"java_pid" + currentPid + (isStatic ? "_static.jsa" : "_dynamic.jsa");
|
||||
|
||||
// delete if archive file aready exists
|
||||
File fileArchive = new File(archiveFile);
|
||||
if (fileArchive.exists()) {
|
||||
fileArchive.delete();
|
||||
}
|
||||
if (isStatic) {
|
||||
String listFile = archiveFile + ".classlist";
|
||||
File fileList = new File(listFile);
|
||||
if (fileList.exists()) {
|
||||
fileList.delete();
|
||||
}
|
||||
dumpClassList(listFile);
|
||||
String jdkHome = System.getProperty("java.home");
|
||||
String classPath = System.getProperty("java.class.path");
|
||||
List<String> cmds = new ArrayList<String>();
|
||||
cmds.add(jdkHome + File.separator + "bin" + File.separator + "java"); // java
|
||||
cmds.add("-cp");
|
||||
cmds.add(classPath);
|
||||
cmds.add("-Xlog:cds");
|
||||
cmds.add("-Xshare:dump");
|
||||
cmds.add("-XX:SharedClassListFile=" + listFile);
|
||||
cmds.add("-XX:SharedArchiveFile=" + archiveFile);
|
||||
|
||||
// All runtime args.
|
||||
String[] vmArgs = VM.getRuntimeArguments();
|
||||
if (vmArgs != null) {
|
||||
for (String arg : vmArgs) {
|
||||
if (arg != null && !containsExcludedFlags(arg)) {
|
||||
cmds.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process proc = Runtime.getRuntime().exec(cmds.toArray(new String[0]));
|
||||
|
||||
// Drain stdout/stderr to files in new threads.
|
||||
String stdOutFile = drainOutput(proc.getInputStream(), proc.pid(), "stdout", cmds);
|
||||
String stdErrFile = drainOutput(proc.getErrorStream(), proc.pid(), "stderr", cmds);
|
||||
|
||||
proc.waitFor();
|
||||
// done, delete classlist file.
|
||||
if (fileList.exists()) {
|
||||
fileList.delete();
|
||||
}
|
||||
// Check if archive has been successfully dumped. We won't reach here if exception happens.
|
||||
// Throw exception if file is not created.
|
||||
if (!fileArchive.exists()) {
|
||||
throw new RuntimeException("Archive file " + archiveFile +
|
||||
" is not created, please check stdout file " +
|
||||
stdOutFile + " or stderr file " +
|
||||
stdErrFile + " for more detail");
|
||||
}
|
||||
} else {
|
||||
dumpDynamicArchive(archiveFile);
|
||||
if (!fileArchive.exists()) {
|
||||
throw new RuntimeException("Archive file " + archiveFile +
|
||||
" is not created, please check process " +
|
||||
currentPid + " output for more detail");
|
||||
}
|
||||
}
|
||||
// Everyting goes well, print out the file name.
|
||||
System.out.println((isStatic ? "Static" : " Dynamic") + " dump to file " + archiveFile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
|
@ -63,3 +63,13 @@ JNIEXPORT void JNICALL
|
|||
Java_jdk_internal_misc_CDS_logLambdaFormInvoker(JNIEnv *env, jclass jcls, jstring line) {
|
||||
JVM_LogLambdaFormInvoker(env, line);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_jdk_internal_misc_CDS_dumpClassList(JNIEnv *env, jclass jcls, jstring fileName) {
|
||||
JVM_DumpClassListToFile(env, fileName);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_jdk_internal_misc_CDS_dumpDynamicArchive(JNIEnv *env, jclass jcls, jstring archiveName) {
|
||||
JVM_DumpDynamicArchive(env, archiveName);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue