Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/hotspot/os/aix/os_aix.cpp
Expand Up @@ -2665,9 +2665,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);
}

Expand Down
4 changes: 1 addition & 3 deletions src/hotspot/os/bsd/os_bsd.cpp
Expand Up @@ -2355,9 +2355,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);
}

Expand Down
4 changes: 1 addition & 3 deletions src/hotspot/os/linux/os_linux.cpp
Expand Up @@ -4968,9 +4968,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);
}

Expand Down
4 changes: 1 addition & 3 deletions src/hotspot/os/windows/os_windows.cpp
Expand Up @@ -4732,9 +4732,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);
}

Expand Down
7 changes: 5 additions & 2 deletions src/hotspot/share/services/diagnosticCommand.cpp
Expand Up @@ -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) {
Expand All @@ -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) :
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/services/diagnosticCommand.hpp
Expand Up @@ -314,6 +314,7 @@ class HeapDumpDCmd : public DCmdWithParser {
DCmdArgument<char*> _filename;
DCmdArgument<bool> _all;
DCmdArgument<jlong> _gzip;
DCmdArgument<bool> _overwrite;
public:
HeapDumpDCmd(outputStream* output, bool heap);
static const char* name() {
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/services/heapDumper.cpp
Expand Up @@ -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
Expand All @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/services/heapDumper.hpp
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/services/heapDumperCompression.cpp
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/services/heapDumperCompression.hpp
Expand Up @@ -61,10 +61,11 @@ class AbstractWriter : public CHeapObj<mtInternal> {
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();

Expand Down
15 changes: 11 additions & 4 deletions test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpTest.java
Expand Up @@ -50,13 +50,15 @@
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);
Expand Down Expand Up @@ -85,7 +87,12 @@ private void verifyHeapDump(File dump) {
/* 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);
}
}