Skip to content

Commit 7a7b9ed

Browse files
committed
8353727: HeapDumpPath doesn't expand %p
Reviewed-by: stuefe, lmesnik
1 parent c3e0439 commit 7a7b9ed

File tree

2 files changed

+34
-61
lines changed

2 files changed

+34
-61
lines changed

src/hotspot/share/services/heapDumper.cpp

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "oops/objArrayOop.inline.hpp"
4444
#include "oops/oop.inline.hpp"
4545
#include "oops/typeArrayOop.inline.hpp"
46+
#include "runtime/arguments.hpp"
4647
#include "runtime/continuationWrapper.inline.hpp"
4748
#include "runtime/frame.inline.hpp"
4849
#include "runtime/handles.inline.hpp"
@@ -2747,77 +2748,50 @@ void HeapDumper::dump_heap() {
27472748
void HeapDumper::dump_heap(bool oome) {
27482749
static char base_path[JVM_MAXPATHLEN] = {'\0'};
27492750
static uint dump_file_seq = 0;
2750-
char* my_path;
2751+
char my_path[JVM_MAXPATHLEN];
27512752
const int max_digit_chars = 20;
2752-
2753-
const char* dump_file_name = "java_pid";
2754-
const char* dump_file_ext = HeapDumpGzipLevel > 0 ? ".hprof.gz" : ".hprof";
2753+
const char* dump_file_name = HeapDumpGzipLevel > 0 ? "java_pid%p.hprof.gz" : "java_pid%p.hprof";
27552754

27562755
// The dump file defaults to java_pid<pid>.hprof in the current working
27572756
// directory. HeapDumpPath=<file> can be used to specify an alternative
27582757
// dump file name or a directory where dump file is created.
27592758
if (dump_file_seq == 0) { // first time in, we initialize base_path
2760-
// Calculate potentially longest base path and check if we have enough
2761-
// allocated statically.
2762-
const size_t total_length =
2763-
(HeapDumpPath == nullptr ? 0 : strlen(HeapDumpPath)) +
2764-
strlen(os::file_separator()) + max_digit_chars +
2765-
strlen(dump_file_name) + strlen(dump_file_ext) + 1;
2766-
if (total_length > sizeof(base_path)) {
2759+
// Set base path (name or directory, default or custom, without seq no), doing %p substitution.
2760+
const char *path_src = (HeapDumpPath != nullptr && HeapDumpPath[0] != '\0') ? HeapDumpPath : dump_file_name;
2761+
if (!Arguments::copy_expand_pid(path_src, strlen(path_src), base_path, JVM_MAXPATHLEN - max_digit_chars)) {
27672762
warning("Cannot create heap dump file. HeapDumpPath is too long.");
27682763
return;
27692764
}
2770-
2771-
bool use_default_filename = true;
2772-
if (HeapDumpPath == nullptr || HeapDumpPath[0] == '\0') {
2773-
// HeapDumpPath=<file> not specified
2774-
} else {
2775-
strcpy(base_path, HeapDumpPath);
2776-
// check if the path is a directory (must exist)
2777-
DIR* dir = os::opendir(base_path);
2778-
if (dir == nullptr) {
2779-
use_default_filename = false;
2780-
} else {
2781-
// HeapDumpPath specified a directory. We append a file separator
2782-
// (if needed).
2783-
os::closedir(dir);
2784-
size_t fs_len = strlen(os::file_separator());
2785-
if (strlen(base_path) >= fs_len) {
2786-
char* end = base_path;
2787-
end += (strlen(base_path) - fs_len);
2788-
if (strcmp(end, os::file_separator()) != 0) {
2789-
strcat(base_path, os::file_separator());
2790-
}
2765+
// Check if the path is an existing directory
2766+
DIR* dir = os::opendir(base_path);
2767+
if (dir != nullptr) {
2768+
os::closedir(dir);
2769+
// Path is a directory. Append a file separator (if needed).
2770+
size_t fs_len = strlen(os::file_separator());
2771+
if (strlen(base_path) >= fs_len) {
2772+
char* end = base_path;
2773+
end += (strlen(base_path) - fs_len);
2774+
if (strcmp(end, os::file_separator()) != 0) {
2775+
strcat(base_path, os::file_separator());
27912776
}
27922777
}
2778+
// Then add the default name, with %p substitution. Use my_path temporarily.
2779+
if (!Arguments::copy_expand_pid(dump_file_name, strlen(dump_file_name), my_path, JVM_MAXPATHLEN - max_digit_chars)) {
2780+
warning("Cannot create heap dump file. HeapDumpPath is too long.");
2781+
return;
2782+
}
2783+
const size_t dlen = strlen(base_path);
2784+
jio_snprintf(&base_path[dlen], sizeof(base_path) - dlen, "%s", my_path);
27932785
}
2794-
// If HeapDumpPath wasn't a file name then we append the default name
2795-
if (use_default_filename) {
2796-
const size_t dlen = strlen(base_path); // if heap dump dir specified
2797-
jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s",
2798-
dump_file_name, os::current_process_id(), dump_file_ext);
2799-
}
2800-
const size_t len = strlen(base_path) + 1;
2801-
my_path = (char*)os::malloc(len, mtInternal);
2802-
if (my_path == nullptr) {
2803-
warning("Cannot create heap dump file. Out of system memory.");
2804-
return;
2805-
}
2806-
strncpy(my_path, base_path, len);
2786+
strncpy(my_path, base_path, JVM_MAXPATHLEN);
28072787
} else {
28082788
// Append a sequence number id for dumps following the first
28092789
const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0
2810-
my_path = (char*)os::malloc(len, mtInternal);
2811-
if (my_path == nullptr) {
2812-
warning("Cannot create heap dump file. Out of system memory.");
2813-
return;
2814-
}
28152790
jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq);
28162791
}
28172792
dump_file_seq++; // increment seq number for next time we dump
28182793

28192794
HeapDumper dumper(false /* no GC before heap dump */,
28202795
oome /* pass along out-of-memory-error flag */);
28212796
dumper.dump(my_path, tty, HeapDumpGzipLevel);
2822-
os::free(my_path);
28232797
}

test/hotspot/jtreg/runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -71,10 +71,12 @@ public static void main(String[] args) throws Exception {
7171
}
7272
}
7373
test(args[1]);
74+
System.out.println("PASSED");
7475
}
7576

7677
static void test(String type) throws Exception {
77-
String heapdumpFilename = type + ".hprof";
78+
// Test using %p pid substitution in HeapDumpPath:
79+
String heapdumpFilename = type + ".%p.hprof";
7880
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+HeapDumpOnOutOfMemoryError",
7981
"-XX:HeapDumpPath=" + heapdumpFilename,
8082
// Note: When trying to provoke a metaspace OOM we may generate a lot of classes. In debug VMs this
@@ -94,13 +96,10 @@ static void test(String type) throws Exception {
9496

9597
OutputAnalyzer output = new OutputAnalyzer(pb.start());
9698
output.stdoutShouldNotBeEmpty();
97-
output.shouldContain("Dumping heap to " + type + ".hprof");
98-
File dump = new File(heapdumpFilename);
99-
Asserts.assertTrue(dump.exists() && dump.isFile(),
100-
"Could not find dump file " + dump.getAbsolutePath());
101-
102-
HprofParser.parse(new File(heapdumpFilename));
103-
System.out.println("PASSED");
99+
String expectedHeapdumpFilename = type + "." + output.pid() + ".hprof";
100+
output.shouldContain("Dumping heap to " + expectedHeapdumpFilename);
101+
File dump = new File(expectedHeapdumpFilename);
102+
Asserts.assertTrue(dump.exists() && dump.isFile(), "Expected heap dump file " + dump.getAbsolutePath());
103+
HprofParser.parse(new File(expectedHeapdumpFilename));
104104
}
105-
106105
}

0 commit comments

Comments
 (0)