From 5bf1b9a53485b571095b934f65c2d6143f748d4f Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 25 May 2023 19:02:09 +0000 Subject: [PATCH] 8283520: JFR: Memory leak in dcmd_arena Backport-of: 6a8be358d2af34fab8798077202b998badaa5d54 --- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 17 ++++++++--------- .../share/jfr/support/jfrThreadLocal.cpp | 18 ++++++++++++++++++ .../share/jfr/support/jfrThreadLocal.hpp | 4 ++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 875e7f8e475..a21a4fa7d48 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -30,6 +30,7 @@ #include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" +#include "jfr/support/jfrThreadLocal.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" #include "logging/logMessage.hpp" @@ -311,12 +312,10 @@ static void initialize_dummy_descriptors(GrowableArray* array // we keep them in a thread local arena. The arena is reset between invocations. static THREAD_LOCAL Arena* dcmd_arena = NULL; -static void prepare_dcmd_string_arena() { - if (dcmd_arena == NULL) { - dcmd_arena = new (mtTracing) Arena(mtTracing); - } else { - dcmd_arena->destruct_contents(); // will grow on next allocation - } +static void prepare_dcmd_string_arena(JavaThread* jt) { + dcmd_arena = JfrThreadLocal::dcmd_arena(jt); + assert(dcmd_arena != nullptr, "invariant"); + dcmd_arena->destruct_contents(); // will grow on next allocation } static char* dcmd_arena_allocate(size_t size) { @@ -324,7 +323,7 @@ static char* dcmd_arena_allocate(size_t size) { return (char*)dcmd_arena->Amalloc(size); } -static const char* get_as_dcmd_arena_string(oop string, JavaThread* t) { +static const char* get_as_dcmd_arena_string(oop string) { char* str = NULL; const typeArrayOop value = java_lang_String::value(string); if (value != NULL) { @@ -345,7 +344,7 @@ static const char* read_string_field(oop argument, const char* field_name, TRAPS args.set_receiver(argument); JfrJavaSupport::get_field(&args, THREAD); const oop string_oop = result.get_oop(); - return string_oop != NULL ? get_as_dcmd_arena_string(string_oop, (JavaThread*)THREAD) : NULL; + return string_oop != NULL ? get_as_dcmd_arena_string(string_oop) : NULL; } static bool read_boolean_field(oop argument, const char* field_name, TRAPS) { @@ -394,7 +393,7 @@ GrowableArray* JfrDCmd::argument_info_array() const { assert(arguments->is_array(), "must be array"); const int num_arguments = arguments->length(); assert(num_arguments == _num_arguments, "invariant"); - prepare_dcmd_string_arena(); + prepare_dcmd_string_arena(thread); for (int i = 0; i < num_arguments; ++i) { DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread); assert(dai != NULL, "invariant"); diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 48b6d657ebc..1c4fabc75c3 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -34,6 +34,7 @@ #include "jfr/recorder/storage/jfrStorage.hpp" #include "jfr/support/jfrThreadLocal.hpp" #include "memory/allocation.inline.hpp" +#include "memory/arena.hpp" #include "runtime/os.hpp" #include "runtime/thread.inline.hpp" #include "utilities/sizes.hpp" @@ -46,6 +47,7 @@ JfrThreadLocal::JfrThreadLocal() : _load_barrier_buffer_epoch_0(NULL), _load_barrier_buffer_epoch_1(NULL), _stackframes(NULL), + _dcmd_arena(nullptr), _trace_id(JfrTraceId::assign_thread_id()), _thread(), _data_lost(0), @@ -142,6 +144,10 @@ void JfrThreadLocal::release(Thread* t) { _load_barrier_buffer_epoch_1->set_retired(); _load_barrier_buffer_epoch_1 = NULL; } + if (_dcmd_arena != nullptr) { + delete _dcmd_arena; + _dcmd_arena = nullptr; + } } void JfrThreadLocal::release(JfrThreadLocal* tl, Thread* t) { @@ -218,3 +224,15 @@ void JfrThreadLocal::include(Thread* t) { u4 JfrThreadLocal::stackdepth() const { return _stackdepth != 0 ? _stackdepth : (u4)JfrOptionSet::stackdepth(); } + +Arena* JfrThreadLocal::dcmd_arena(JavaThread* jt) { + assert(jt != nullptr, "invariant"); + JfrThreadLocal* tl = jt->jfr_thread_local(); + Arena* arena = tl->_dcmd_arena; + if (arena != nullptr) { + return arena; + } + arena = new (mtTracing) Arena(mtTracing); + tl->_dcmd_arena = arena; + return arena; +} diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp index 7e4a0819cf2..ab7d6170cdb 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp @@ -28,6 +28,7 @@ #include "jfr/utilities/jfrBlob.hpp" #include "jfr/utilities/jfrTypes.hpp" +class Arena; class JavaThread; class JfrBuffer; class JfrStackFrame; @@ -42,6 +43,7 @@ class JfrThreadLocal { JfrBuffer* _load_barrier_buffer_epoch_0; JfrBuffer* _load_barrier_buffer_epoch_1; mutable JfrStackFrame* _stackframes; + Arena* _dcmd_arena; mutable traceid _trace_id; JfrBlobHandle _thread; u8 _data_lost; @@ -219,6 +221,8 @@ class JfrThreadLocal { return _dead; } + static Arena* dcmd_arena(JavaThread* jt); + bool has_thread_blob() const; void set_thread_blob(const JfrBlobHandle& handle); const JfrBlobHandle& thread_blob() const; -- 2.43.2