diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 36656515942..4a54fd8d0a9 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1788,7 +1788,7 @@ void CodeCache::log_state(outputStream* st) { } #ifdef LINUX -void CodeCache::write_perf_map(const char* filename) { +void CodeCache::write_perf_map(const char* filename, outputStream* st) { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); // Perf expects to find the map file at /tmp/perf-<pid>.map @@ -1801,7 +1801,7 @@ void CodeCache::write_perf_map(const char* filename) { fileStream fs(filename, "w"); if (!fs.is_open()) { - log_warning(codecache)("Failed to create %s for perf map", filename); + st->print_cr("Warning: Failed to create %s for perf map", filename); return; } diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 8fcbf32b644..565f600453e 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -223,7 +223,7 @@ class CodeCache : AllStatic { static void print_trace(const char* event, CodeBlob* cb, uint size = 0) PRODUCT_RETURN; static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); - LINUX_ONLY(static void write_perf_map(const char* filename = nullptr);) + LINUX_ONLY(static void write_perf_map(const char* filename, outputStream* st);) // Prints warnings and error messages to outputStream static const char* get_code_heap_name(CodeBlobType code_blob_type) { return (heap_available(code_blob_type) ? get_code_heap(code_blob_type)->name() : "Unused"); } static void report_codemem_full(CodeBlobType code_blob_type, bool print); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 7ffe56d9715..23df464aba8 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -484,7 +484,7 @@ void before_exit(JavaThread* thread, bool halt) { #ifdef LINUX if (DumpPerfMapAtExit) { - CodeCache::write_perf_map(); + CodeCache::write_perf_map(nullptr, tty); } if (PrintMemoryMapAtExit) { MemMapPrinter::print_all_mappings(tty); diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 7d2325c16b6..e6328e95abd 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -865,7 +865,7 @@ void PerfMapDCmd::execute(DCmdSource source, TRAPS) { // The check for _filename.is_set() is because we don't want to use // DEFAULT_PERFMAP_FILENAME, since it is meant as a description // of the default, not the actual default. - CodeCache::write_perf_map(_filename.is_set() ? _filename.value() : nullptr); + CodeCache::write_perf_map(_filename.is_set() ? _filename.value() : nullptr, output()); } #endif // LINUX diff --git a/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java index 6bbe62044d0..7a72efd68ba 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/compiler/PerfMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -113,4 +113,16 @@ public class PerfMapTest { run(new JMXExecutor(), "Compiler.perfmap " + path.toString(), path); Files.deleteIfExists(path); } + + @Test + public void logErrorsDcmdOutputStream() throws IOException { + String test_dir = System.getProperty("test.dir", "."); + Path path = Paths.get("nonexistent", test_dir); + try { + OutputAnalyzer output = new JMXExecutor().execute("Compiler.perfmap %s".formatted(path)); + output.shouldContain("Warning: Failed to create nonexistent/%s for perf map".formatted(test_dir)); + } finally { + Files.deleteIfExists(path); + } + } }