--- old/src/hotspot/share/services/memTracker.cpp 2019-07-04 14:44:53.250785562 +0200 +++ new/src/hotspot/share/services/memTracker.cpp 2019-07-04 14:44:53.038787052 +0200 @@ -175,6 +175,22 @@ return true; } + +static volatile bool g_final_report_did_run = false; +void MemTracker::final_report(outputStream* output) { + // This function is called during both error reporting and normal VM exit. + // However, it should only ever run once. E.g. if the VM crashes after + // printing the final report during normal VM exit, it should not print + // the final report again. In addition, it should be guarded from + // recursive calls in case NMT reporting itself crashes. + if (Atomic::cmpxchg(true, &g_final_report_did_run, false) == false) { + NMT_TrackingLevel level = tracking_level(); + if (level >= NMT_summary) { + report(level == NMT_summary, output); + } + } +} + void MemTracker::report(bool summary_only, outputStream* output) { assert(output != NULL, "No output stream"); MemBaseline baseline; @@ -186,12 +202,9 @@ MemDetailReporter rpt(baseline, output); rpt.report(); output->print("Metaspace:"); - // Metadata reporting requires a safepoint, so avoid it if VM is not in good state. - assert(!VMError::fatal_error_in_progress(), "Do not report metadata in error report"); - VM_PrintMetadata vmop(output, K, - MetaspaceUtils::rf_show_loaders | - MetaspaceUtils::rf_break_down_by_spacetype); - VMThread::execute(&vmop); + // The basic metaspace report avoids any locking and should be safe to + // be called at any time. + MetaspaceUtils::print_basic_report(output, K); } } } --- old/src/hotspot/share/services/memTracker.hpp 2019-07-04 14:44:53.798781712 +0200 +++ new/src/hotspot/share/services/memTracker.hpp 2019-07-04 14:44:53.590783174 +0200 @@ -271,13 +271,7 @@ } } - static void final_report(outputStream* output) { - NMT_TrackingLevel level = tracking_level(); - if (level >= NMT_summary) { - report(level == NMT_summary, output); - } - } - + static void final_report(outputStream* output); // Stored baseline static inline MemBaseline& get_baseline() { --- old/src/hotspot/share/utilities/vmError.cpp 2019-07-04 14:44:54.338777917 +0200 +++ new/src/hotspot/share/utilities/vmError.cpp 2019-07-04 14:44:54.134779351 +0200 @@ -1527,6 +1527,12 @@ log.set_fd(-1); } + // Print out NMT statistics if this was desired. + if (PrintNMTStatistics) { + fdStream fds(fd_out); + MemTracker::final_report(&fds); + } + static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) { skip_replay = true;