8267666: Add option to jcmd GC.heap_dump to use existing file

Reviewed-by: rschmelter, clanger
This commit is contained in:
Anton Kozlov 2021-07-12 11:12:52 +00:00
parent 8973867fb9
commit 7cbb67a3f8
11 changed files with 27 additions and 23 deletions

View File

@ -2660,9 +2660,7 @@ int os::open(const char *path, int oflag, int mode) {
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
int oflags = O_WRONLY | O_CREAT;
if (!rewrite_existing) {
oflags |= O_EXCL;
}
oflags |= rewrite_existing ? O_TRUNC : O_EXCL;
return ::open64(path, oflags, S_IREAD | S_IWRITE);
}

View File

@ -2350,9 +2350,7 @@ int os::open(const char *path, int oflag, int mode) {
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
int oflags = O_WRONLY | O_CREAT;
if (!rewrite_existing) {
oflags |= O_EXCL;
}
oflags |= rewrite_existing ? O_TRUNC : O_EXCL;
return ::open(path, oflags, S_IREAD | S_IWRITE);
}

View File

@ -4963,9 +4963,7 @@ int os::open(const char *path, int oflag, int mode) {
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
int oflags = O_WRONLY | O_CREAT;
if (!rewrite_existing) {
oflags |= O_EXCL;
}
oflags |= rewrite_existing ? O_TRUNC : O_EXCL;
return ::open64(path, oflags, S_IREAD | S_IWRITE);
}

View File

@ -4801,9 +4801,7 @@ bool os::dir_is_empty(const char* path) {
// create binary file, rewriting existing file if required
int os::create_binary_file(const char* path, bool rewrite_existing) {
int oflags = _O_CREAT | _O_WRONLY | _O_BINARY;
if (!rewrite_existing) {
oflags |= _O_EXCL;
}
oflags |= rewrite_existing ? _O_TRUNC : _O_EXCL;
return ::open(path, oflags, _S_IREAD | _S_IWRITE);
}

View File

@ -468,10 +468,13 @@ HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
"BOOLEAN", false, "false"),
_gzip("-gz", "If specified, the heap dump is written in gzipped format "
"using the given compression level. 1 (recommended) is the fastest, "
"9 the strongest compression.", "INT", false, "1") {
"9 the strongest compression.", "INT", false, "1"),
_overwrite("-overwrite", "If specified, the dump file will be overwritten if it exists",
"BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_all);
_dcmdparser.add_dcmd_argument(&_filename);
_dcmdparser.add_dcmd_option(&_gzip);
_dcmdparser.add_dcmd_option(&_overwrite);
}
void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
@ -490,7 +493,7 @@ void HeapDumpDCmd::execute(DCmdSource source, TRAPS) {
// This helps reduces the amount of unreachable objects in the dump
// and makes it easier to browse.
HeapDumper dumper(!_all.value() /* request GC if _all is false*/);
dumper.dump(_filename.value(), output(), (int) level);
dumper.dump(_filename.value(), output(), (int) level, _overwrite.value());
}
ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) :

View File

@ -314,6 +314,7 @@ protected:
DCmdArgument<char*> _filename;
DCmdArgument<bool> _all;
DCmdArgument<jlong> _gzip;
DCmdArgument<bool> _overwrite;
public:
HeapDumpDCmd(outputStream* output, bool heap);
static const char* name() {

View File

@ -1905,7 +1905,7 @@ void VM_HeapDumper::dump_stack_traces() {
}
// dump the heap to given path.
int HeapDumper::dump(const char* path, outputStream* out, int compression) {
int HeapDumper::dump(const char* path, outputStream* out, int compression, bool overwrite) {
assert(path != NULL && strlen(path) > 0, "path missing");
// print message in interactive case
@ -1928,7 +1928,7 @@ int HeapDumper::dump(const char* path, outputStream* out, int compression) {
}
}
DumpWriter writer(new (std::nothrow) FileWriter(path), compressor);
DumpWriter writer(new (std::nothrow) FileWriter(path, overwrite), compressor);
if (writer.error() != NULL) {
set_error(writer.error());

View File

@ -71,7 +71,7 @@ class HeapDumper : public StackObj {
// dumps the heap to the specified file, returns 0 if success.
// additional info is written to out if not NULL.
// compression >= 0 creates a gzipped file with the given compression level.
int dump(const char* path, outputStream* out = NULL, int compression = -1);
int dump(const char* path, outputStream* out = NULL, int compression = -1, bool overwrite = false);
// returns error message (resource allocated), or NULL if no error
char* error_as_C_string() const;

View File

@ -34,7 +34,7 @@
char const* FileWriter::open_writer() {
assert(_fd < 0, "Must not already be open");
_fd = os::create_binary_file(_path, false); // don't replace existing file
_fd = os::create_binary_file(_path, _overwrite);
if (_fd < 0) {
return os::strerror(errno);

View File

@ -61,10 +61,11 @@ public:
class FileWriter : public AbstractWriter {
private:
char const* _path;
bool _overwrite;
int _fd;
public:
FileWriter(char const* path) : _path(path), _fd(-1) { }
FileWriter(char const* path, bool overwrite) : _path(path), _overwrite(overwrite), _fd(-1) { }
~FileWriter();

View File

@ -50,13 +50,15 @@ import jdk.test.lib.dcmd.PidJcmdExecutor;
public class HeapDumpTest {
protected String heapDumpArgs = "";
public void run(CommandExecutor executor) throws IOException {
public void run(CommandExecutor executor, boolean overwrite) throws IOException {
File dump = new File("jcmd.gc.heap_dump." + System.currentTimeMillis() + ".hprof");
if (dump.exists()) {
if (!overwrite && dump.exists()) {
dump.delete();
} else if (overwrite) {
dump.createNewFile();
}
String cmd = "GC.heap_dump " + heapDumpArgs + " " + dump.getAbsolutePath();
String cmd = "GC.heap_dump " + (overwrite ? "-overwrite " : "") + heapDumpArgs + " " + dump.getAbsolutePath();
executor.execute(cmd);
verifyHeapDump(dump);
@ -85,7 +87,12 @@ public class HeapDumpTest {
/* GC.heap_dump is not available over JMX, running jcmd pid executor instead */
@Test
public void pid() throws IOException {
run(new PidJcmdExecutor());
run(new PidJcmdExecutor(), false);
}
@Test
public void pidRewrite() throws IOException {
run(new PidJcmdExecutor(), true);
}
}