From 9fe2aa59ffde71879eeee5cfa10919468c253b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 29 Jul 2025 11:40:55 +0000 Subject: [PATCH] 8356587: Missing object ID X in pool jdk.types.Method Reviewed-by: egahlin Backport-of: a34994476e8f4783c9f5a83a9c3db63ad605b323 --- .../instrumentation/jfrClassTransformer.cpp | 7 +- .../instrumentation/jfrClassTransformer.hpp | 4 +- src/hotspot/share/jfr/jfr.cpp | 7 +- src/hotspot/share/jfr/jfr.hpp | 2 +- .../recorder/checkpoint/types/jfrTypeSet.cpp | 5 +- .../checkpoint/types/jfrTypeSetUtils.hpp | 2 +- .../checkpoint/types/traceid/jfrTraceId.hpp | 8 +- .../types/traceid/jfrTraceId.inline.hpp | 32 ++-- .../types/traceid/jfrTraceIdBits.inline.hpp | 4 +- .../traceid/jfrTraceIdLoadBarrier.inline.hpp | 32 +++- .../recorder/service/jfrRecorderService.cpp | 2 +- .../stacktrace/jfrStackTraceRepository.cpp | 2 + .../jfr/support/jfrDeprecationManager.cpp | 9 +- .../share/jfr/support/jfrKlassExtension.hpp | 2 - .../share/jfr/support/jfrTraceIdExtension.hpp | 10 +- .../methodtracer/jfrInstrumentedClass.hpp | 8 +- .../methodtracer/jfrMethodProcessor.cpp | 2 + .../support/methodtracer/jfrMethodTracer.cpp | 45 ++--- .../support/methodtracer/jfrMethodTracer.hpp | 4 +- .../support/methodtracer/jfrTraceTagging.cpp | 167 ++++++++++-------- .../support/methodtracer/jfrTraceTagging.hpp | 14 +- .../share/prims/jvmtiRedefineClasses.cpp | 6 +- .../share/runtime/safepointMechanism.cpp | 2 +- .../jfr/internal/consumer/ConstantMap.java | 2 +- 24 files changed, 203 insertions(+), 175 deletions(-) diff --git a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp index 27480999720..b9bedff0f9d 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.cpp @@ -132,14 +132,14 @@ InstanceKlass* JfrClassTransformer::create_new_instance_klass(InstanceKlass* ik, } // Redefining / retransforming? -const Klass* JfrClassTransformer::find_existing_klass(const InstanceKlass* ik, JavaThread* thread) { +const InstanceKlass* JfrClassTransformer::find_existing_klass(const InstanceKlass* ik, JavaThread* thread) { assert(ik != nullptr, "invariant"); assert(thread != nullptr, "invariant"); JvmtiThreadState* const state = thread->jvmti_thread_state(); return state != nullptr ? klass_being_redefined(ik, state) : nullptr; } -const Klass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state) { +const InstanceKlass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state) { assert(ik != nullptr, "invariant"); assert(state != nullptr, "invariant"); const GrowableArray* const redef_klasses = state->get_classes_being_redefined(); @@ -149,9 +149,10 @@ const Klass* JfrClassTransformer::klass_being_redefined(const InstanceKlass* ik, for (int i = 0; i < redef_klasses->length(); ++i) { const Klass* const existing_klass = redef_klasses->at(i); assert(existing_klass != nullptr, "invariant"); + assert(existing_klass->is_instance_klass(), "invariant"); if (ik->name() == existing_klass->name() && ik->class_loader_data() == existing_klass->class_loader_data()) { // 'ik' is a scratch klass. Return the klass being redefined. - return existing_klass; + return InstanceKlass::cast(existing_klass); } } return nullptr; diff --git a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.hpp b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.hpp index 3a2629bbc97..a05ac6198b8 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.hpp +++ b/src/hotspot/share/jfr/instrumentation/jfrClassTransformer.hpp @@ -38,10 +38,10 @@ class InstanceKlass; class JfrClassTransformer : AllStatic { private: static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPS); - static const Klass* klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state); + static const InstanceKlass* klass_being_redefined(const InstanceKlass* ik, JvmtiThreadState* state); public: - static const Klass* find_existing_klass(const InstanceKlass* ik, JavaThread* thread); + static const InstanceKlass* find_existing_klass(const InstanceKlass* ik, JavaThread* thread); static InstanceKlass* create_instance_klass(InstanceKlass*& ik, ClassFileStream* stream, bool is_initial_load, JavaThread* thread); static void copy_traceid(const InstanceKlass* ik, const InstanceKlass* new_ik); static void transfer_cached_class_file_data(InstanceKlass* ik, InstanceKlass* new_ik, const ClassFileParser& parser, JavaThread* thread); diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp index f43aab6bdfc..4bd57b3c324 100644 --- a/src/hotspot/share/jfr/jfr.cpp +++ b/src/hotspot/share/jfr/jfr.cpp @@ -36,6 +36,7 @@ #include "jfr/support/jfrResolution.hpp" #include "jfr/support/jfrThreadLocal.hpp" #include "jfr/support/methodtracer/jfrMethodTracer.hpp" +#include "jfr/support/methodtracer/jfrTraceTagging.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceKlass.inline.hpp" #include "oops/klass.hpp" @@ -88,12 +89,10 @@ void Jfr::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS) } } -void Jfr::on_klass_redefinition(const InstanceKlass* ik, Thread* thread) { - assert(JfrMethodTracer::in_use(), "invariant"); - JfrMethodTracer::on_klass_redefinition(ik, thread); +void Jfr::on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass) { + JfrTraceTagging::on_klass_redefinition(ik, scratch_klass); } - bool Jfr::is_excluded(Thread* t) { return JfrJavaSupport::is_excluded(t); } diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp index 471389dfb8b..b053c6445ef 100644 --- a/src/hotspot/share/jfr/jfr.hpp +++ b/src/hotspot/share/jfr/jfr.hpp @@ -61,7 +61,7 @@ class Jfr : AllStatic { static void include_thread(Thread* thread); static void exclude_thread(Thread* thread); static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS); - static void on_klass_redefinition(const InstanceKlass* ik, Thread* thread); + static void on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass); static void on_thread_start(Thread* thread); static void on_thread_exit(Thread* thread); static void on_resolution(const CallInfo& info, TRAPS); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index a8248b7714e..69f002138ec 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -533,8 +533,9 @@ static void clear_method_tracer_klasses() { static void do_unloading_klass(Klass* klass) { assert(klass != nullptr, "invariant"); assert(_subsystem_callback != nullptr, "invariant"); - if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_scratch_class()) { - return; + if (!used(klass) && klass->is_instance_klass() && InstanceKlass::cast(klass)->is_scratch_class()) { + SET_TRANSIENT(klass); + assert(used(klass), "invariant"); } if (JfrKlassUnloading::on_unload(klass)) { if (JfrTraceId::has_sticky_bit(klass)) { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp index 1fb7db1b9ed..657aee9dc53 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp @@ -152,7 +152,7 @@ public: if (!klass->is_instance_klass()) { return false; } - return _current_epoch ? METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_PREVIOUS_EPOCH(klass); + return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass); } }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp index 378d1af23cc..f10782be0ea 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp @@ -30,6 +30,7 @@ #include "memory/allStatic.hpp" class ClassLoaderData; +class InstanceKlass; class Klass; class Method; class ModuleEntry; @@ -86,7 +87,6 @@ class JfrTraceId : public AllStatic { // through load barrier static traceid load(const Klass* klass); - static traceid load_previous_epoch(const Klass* klass); static traceid load(jclass jc, bool raw = false); static traceid load(const Method* method); static traceid load(const Klass* klass, const Method* method); @@ -146,10 +146,8 @@ class JfrTraceId : public AllStatic { static void set_sticky_bit(const Method* method); static void clear_sticky_bit(const Klass* k); static void clear_sticky_bit(const Method* method); - static bool has_timing_bit(const Klass* k); - static void set_timing_bit(const Klass* k); - static void clear_timing_bit(const Klass* k); - + static bool has_timing_bit(const InstanceKlass* scratch_klass); + static void set_timing_bit(const InstanceKlass* scratch_klass); }; #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp index 2b2c435d986..03647bdeae2 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp @@ -32,6 +32,7 @@ #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp" #include "jfr/support/jfrKlassExtension.hpp" +#include "oops/instanceKlass.hpp" #include "oops/klass.hpp" #include "runtime/javaThread.inline.hpp" #include "runtime/mutexLocker.hpp" @@ -81,10 +82,6 @@ inline traceid JfrTraceId::load_leakp_previous_epoch(const Klass* klass, const M return JfrTraceIdLoadBarrier::load_leakp_previous_epoch(klass, method); } -inline traceid JfrTraceId::load_previous_epoch(const Klass* klass) { - return JfrTraceIdLoadBarrier::load_previous_epoch(klass); -} - template inline traceid raw_load(const T* t) { assert(t != nullptr, "invariant"); @@ -198,6 +195,7 @@ inline void JfrTraceId::set_sticky_bit(const Method* method) { assert(method != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); assert(!has_sticky_bit(method), "invariant"); + assert(!method->is_old(), "invariant"); SET_METHOD_STICKY_BIT(method); assert(has_sticky_bit(method), "invariant"); } @@ -205,30 +203,22 @@ inline void JfrTraceId::set_sticky_bit(const Method* method) { inline void JfrTraceId::clear_sticky_bit(const Method* method) { assert(method != nullptr, "invarriant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); + assert(!method->is_old(), "invariant"); assert(JfrTraceId::has_sticky_bit(method), "invariant"); CLEAR_STICKY_BIT_METHOD(method); assert(!JfrTraceId::has_sticky_bit(method), "invariant"); } -inline bool JfrTraceId::has_timing_bit(const Klass* k) { - assert(k != nullptr, "invariant"); - return HAS_TIMING_BIT(k); +inline bool JfrTraceId::has_timing_bit(const InstanceKlass* scratch_klass) { + assert(scratch_klass != nullptr, "invariant"); + return HAS_TIMING_BIT(scratch_klass); } -inline void JfrTraceId::set_timing_bit(const Klass* k) { - assert(k != nullptr, "invariant"); - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - assert(!has_timing_bit(k), "invariant"); - SET_TIMING_BIT(k); - assert(has_timing_bit(k), "invariant"); -} - -inline void JfrTraceId::clear_timing_bit(const Klass* k) { - assert(k != nullptr, "invarriant"); - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - assert(JfrTraceId::has_timing_bit(k), "invariant"); - CLEAR_TIMING_BIT(k); - assert(!JfrTraceId::has_timing_bit(k), "invariant"); +inline void JfrTraceId::set_timing_bit(const InstanceKlass* scratch_klass) { + assert(scratch_klass != nullptr, "invariant"); + assert(!has_timing_bit(scratch_klass), "invariant"); + SET_TIMING_BIT(scratch_klass); + assert(has_timing_bit(scratch_klass), "invariant"); } #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEID_INLINE_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp index 120c750b2a8..034b8e653cf 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,7 +78,7 @@ inline uint8_t* traceid_meta_byte(const T* ptr) { template <> inline uint8_t* traceid_meta_byte(const Method* ptr) { assert(ptr != nullptr, "invariant"); - return ptr->trace_meta_addr(); + return ptr->trace_flags_meta_addr(); } inline uint8_t traceid_and(uint8_t bits, uint8_t current) { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp index ac1c11af2f8..c2b63840107 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp @@ -86,6 +86,27 @@ inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) { return TRACE_ID(klass); } +inline const Method* latest_version(const Klass* klass, const Method* method) { + assert(klass != nullptr, "invariant"); + assert(method != nullptr, "invariant"); + assert(klass == method->method_holder(), "invariant"); + assert(method->is_old(), "invariant"); + const InstanceKlass* const ik = InstanceKlass::cast(klass); + assert(ik->has_been_redefined(), "invariant"); + const Method* const latest_version = ik->method_with_orig_idnum(method->orig_method_idnum()); + if (latest_version == nullptr) { + assert(AllowRedefinitionToAddDeleteMethods, "invariant"); + // method has been removed. Return old version. + return method; + } + assert(latest_version != nullptr, "invariant"); + assert(latest_version != method, "invariant"); + assert(!latest_version->is_old(), "invariant"); + assert(latest_version->orig_method_idnum() == method->orig_method_idnum(), "invariant"); + assert(latest_version->name() == method->name() && latest_version->signature() == method->signature(), "invariant"); + return latest_version; +} + inline traceid JfrTraceIdLoadBarrier::load(const Method* method) { return load(method->method_holder(), method); } @@ -93,6 +114,9 @@ inline traceid JfrTraceIdLoadBarrier::load(const Method* method) { inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); assert(method != nullptr, "invariant"); + if (method->is_old()) { + method = latest_version(klass, method); + } if (should_tag(method)) { SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass); SET_METHOD_FLAG_USED_THIS_EPOCH(method); @@ -111,6 +135,9 @@ inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Method* method) { inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); assert(method != nullptr, "invariant"); + if (method->is_old()) { + method = latest_version(klass, method); + } SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass); SET_METHOD_FLAG_USED_THIS_EPOCH(method); assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); @@ -123,11 +150,12 @@ inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) { if (cld->has_class_mirror_holder()) { return 0; } + const traceid id = set_used_and_get(cld); const Klass* const class_loader_klass = cld->class_loader_klass(); if (class_loader_klass != nullptr) { load(class_loader_klass); } - return set_used_and_get(cld); + return id; } inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) { @@ -158,6 +186,7 @@ inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass) { inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); assert(method != nullptr, "invariant"); + assert(!method->is_old(), "invariant"); assert(klass == method->method_holder(), "invariant"); assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); if (should_tag(method)) { @@ -175,6 +204,7 @@ inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Metho inline traceid JfrTraceIdLoadBarrier::load_leakp_previous_epoch(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); assert(method != nullptr, "invariant"); + assert(!method->is_old(), "invariant"); assert(klass == method->method_holder(), "invariant"); assert(METHOD_AND_CLASS_USED_PREVIOUS_EPOCH(klass), "invariant"); if (METHOD_FLAG_NOT_USED_PREVIOUS_EPOCH(method)) { diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index 7d1d7ac0a05..f0170bac460 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -645,7 +645,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - total_elements = flush_storage(_storage, _chunkwriter); + total_elements += flush_storage(_storage, _chunkwriter); if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp index 456896fe887..d403a38703e 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp @@ -29,6 +29,7 @@ #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" #include "jfr/support/jfrThreadLocal.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/safepoint.hpp" /* * There are two separate repository instances. @@ -186,6 +187,7 @@ void JfrStackTraceRepository::record_for_leak_profiler(JavaThread* current_threa } traceid JfrStackTraceRepository::add_trace(const JfrStackTrace& stacktrace) { + assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); MutexLocker lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag); assert(stacktrace.number_of_frames() > 0, "invariant"); const size_t index = stacktrace._hash % TABLE_SIZE; diff --git a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp index 4eb8662c209..8fc35ca8dc1 100644 --- a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp +++ b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp @@ -390,15 +390,16 @@ static inline void write_stacktraces(JfrChunkWriter& cw) { _resolved_list.iterate(scw); } -// First, we consolidate all stack trace blobs into a single TYPE_STACKTRACE checkpoint -// and serialize it to the chunk. Then, all events are serialized, and unique type set blobs -// written into the JfrCheckpoint system to be serialized to the chunk upon return. +// First, all events are serialized, and unique type set blobs are written into the +// JfrCheckpoint system to be serialized to the chunk upon return. +// Then, we consolidate all stack trace blobs into a single TYPE_STACKTRACE checkpoint +// and serialize it directly to the chunk. void JfrDeprecationManager::write_edges(JfrChunkWriter& cw, Thread* thread, bool on_error /* false */) { if (_resolved_list.is_nonempty() && JfrEventSetting::is_enabled(JfrDeprecatedInvocationEvent)) { + write_events(cw, thread, on_error); if (has_stacktrace()) { write_stacktraces(cw); } - write_events(cw, thread, on_error); } } diff --git a/src/hotspot/share/jfr/support/jfrKlassExtension.hpp b/src/hotspot/share/jfr/support/jfrKlassExtension.hpp index 8f096347c77..dc5f7aa7e90 100644 --- a/src/hotspot/share/jfr/support/jfrKlassExtension.hpp +++ b/src/hotspot/share/jfr/support/jfrKlassExtension.hpp @@ -40,8 +40,6 @@ #define EVENT_STICKY_BIT 8192 #define IS_EVENT_KLASS(ptr) (((ptr)->trace_id() & (JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS)) != 0) #define IS_EVENT_OR_HOST_KLASS(ptr) (((ptr)->trace_id() & (JDK_JFR_EVENT_KLASS | JDK_JFR_EVENT_SUBKLASS | EVENT_HOST_KLASS)) != 0) -#define KLASS_HAS_STICKY_BIT(ptr) (((ptr)->trace_id() & STICKY_BIT) != 0) -#define ON_KLASS_REDEFINITION(k, t) if (KLASS_HAS_STICKY_BIT(k)) Jfr::on_klass_redefinition(k, t) #define ON_KLASS_CREATION(k, p, t) Jfr::on_klass_creation(k, p, t) #endif // SHARE_JFR_SUPPORT_JFRKLASSEXTENSION_HPP diff --git a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp index c73ece42645..bb0e3e082fe 100644 --- a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp +++ b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,11 +95,13 @@ class JfrTraceFlag { uint8_t* trace_flags_addr() const { \ return _trace_flags.flags_addr(); \ } \ - uint8_t* trace_meta_addr() const { \ + uint8_t* trace_flags_meta_addr() const { \ return _trace_flags.meta_addr(); \ } \ - void copy_trace_flags(uint16_t rhs_flags) const { \ - _trace_flags.set_flags(_trace_flags.flags() | rhs_flags); \ + void copy_trace_flags(const Method* rhm) const { \ + assert(rhm != nullptr, "invariant"); \ + set_trace_flags(rhm->trace_flags()); \ + assert(trace_flags()==rhm->trace_flags(), ""); \ } #endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrInstrumentedClass.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrInstrumentedClass.hpp index eb775581e1f..c3a71ac6933 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrInstrumentedClass.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrInstrumentedClass.hpp @@ -36,16 +36,16 @@ class InstanceKlass; class JfrInstrumentedClass { private: traceid _trace_id; - const InstanceKlass* _instance_klass; + const InstanceKlass* _ik; bool _unloaded; public: - JfrInstrumentedClass(traceid trace_id = 0, const InstanceKlass* instance_klass = nullptr, bool unloaded = false) : - _trace_id(trace_id), _instance_klass(instance_klass), _unloaded(unloaded) { + JfrInstrumentedClass(traceid trace_id = 0, const InstanceKlass* ik = nullptr, bool unloaded = false) : + _trace_id(trace_id), _ik(ik), _unloaded(unloaded) { } const InstanceKlass* instance_klass() const { - return _instance_klass; + return _ik; } traceid trace_id() const { diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrMethodProcessor.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrMethodProcessor.cpp index d3226729beb..16573a77016 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrMethodProcessor.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrMethodProcessor.cpp @@ -67,6 +67,8 @@ void JfrMethodProcessor::update_methods(const InstanceKlass* ik) { const uint32_t idx = _methods->at(i).methods_array_index(); Method* const method = ik_methods->at(idx); assert(method != nullptr, "invariant"); + assert(method->name() == _methods->at(i).name(), "invariant"); + assert(method->signature() == _methods->at(i).signature(), "invariant"); _methods->at(i).set_method(method); // This is to keep the method from being unloaded during redefine / retransform. // Equivalent functionality to that provided by the methodHandle. Unfortunately, diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp index 73701445f70..e667324b51a 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.cpp @@ -128,11 +128,11 @@ void JfrMethodTracer::retransform(JNIEnv* env, const JfrFilterClassClosure& clas } } -static void handle_no_bytecode_result(const Klass* klass) { - assert(klass != nullptr, "invariant"); - if (JfrTraceId::has_sticky_bit(klass)) { +static void handle_no_bytecode_result(const InstanceKlass* ik) { + assert(ik != nullptr, "invariant"); + if (JfrTraceId::has_sticky_bit(ik)) { MutexLocker lock(ClassLoaderDataGraph_lock); - JfrTraceTagging::clear_sticky_bit(InstanceKlass::cast(klass)); + JfrTraceTagging::clear_sticky(ik); } } @@ -143,11 +143,11 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par ResourceMark rm(THREAD); // 1. Is the ik the initial load, i.e.the first InstanceKlass, or a scratch klass, denoting a redefine / retransform? - const Klass* const existing_klass = JfrClassTransformer::find_existing_klass(ik, THREAD); - const bool is_retransform = existing_klass != nullptr; + const InstanceKlass* const existing_ik = JfrClassTransformer::find_existing_klass(ik, THREAD); + const bool is_retransform = existing_ik != nullptr; // 2. Test the ik and its methods against the currently installed filter object. - JfrMethodProcessor mp(is_retransform ? InstanceKlass::cast(existing_klass) : ik, THREAD); + JfrMethodProcessor mp(is_retransform ? existing_ik : ik, THREAD); if (!mp.has_methods()) { return; } @@ -159,7 +159,7 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par // If no bytecode is returned, either an error occurred during transformation, but more // likely the matched instructions were negative, i.e. instructions to remove existing instrumentation // and so Java added no new instrumentation. By not returning a bytecode result, the klass is restored to its original, non-instrumented, version. - handle_no_bytecode_result(is_retransform ? InstanceKlass::cast(existing_klass) : ik); + handle_no_bytecode_result(is_retransform ? existing_ik : ik); return; } // 4. Now create a new InstanceKlass representation from the modified bytecode. @@ -173,13 +173,12 @@ void JfrMethodTracer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& par // Keep the original cached class file data from the existing class. JfrClassTransformer::transfer_cached_class_file_data(ik, new_ik, parser, THREAD); JfrClassTransformer::rewrite_klass_pointer(ik, new_ik, parser, THREAD); // The ik is modified to point to new_ik here. - const InstanceKlass* const existing_ik = InstanceKlass::cast(existing_klass); mp.update_methods(existing_ik); existing_ik->module()->add_read(jdk_jfr_module()); // By setting the sticky bit on the existng klass, we receive a callback into on_klass_redefinition (see below) // when our new methods are installed into the existing klass as part of retransformation / redefinition. // Only when we know our new methods have been installed can we add the klass to the instrumented list (done as part of callback). - JfrTraceTagging::install_sticky_bit_for_retransform_klass(existing_ik, mp.methods(), mp.has_timing()); + JfrTraceTagging::tag_sticky_for_retransform_klass(existing_ik, ik, mp.methods(), mp.has_timing()); return; } // Initial class load. @@ -203,28 +202,22 @@ static inline void log_add(const InstanceKlass* ik) { } } -void JfrMethodTracer::add_timing_entry(const InstanceKlass* ik, traceid klass_id) { - assert(ik != nullptr, "invariant"); +void JfrMethodTracer::add_timing_entry(traceid klass_id) { assert(_timing_entries != nullptr, "invariant"); - if (JfrTraceId::has_timing_bit(ik)) { - JfrTraceId::clear_timing_bit(ik); - _timing_entries->append(klass_id); - } + _timing_entries->append(klass_id); } // At this point we have installed our new retransformed methods into the original klass, which is ik. -// jvmtiRedefineClassses::redefine_single_class() has finished so we are still at a safepoint. -// If the original klass is not already in the list, add it and also dynamically tag all -// artifacts that have the sticky bit set. If the klass has an associated TimedClass, -// also add the klass to the list of _timing_entries for publication. -void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, Thread* thread) { +// jvmtiRedefineClassses::redefine_single_class() is about to finish so we are still at a safepoint. +// If the original klass is not already in the list, add it. If the klass has an associated TimedClass, +// add also the klass_id to the list of _timing_entries for publication. +void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, bool has_timing) { assert(ik != nullptr, "invariant"); assert(!ik->is_scratch_class(), "invarint"); assert(ik->has_been_redefined(), "invariant"); assert(JfrTraceId::has_sticky_bit(ik), "invariant"); assert(in_use(), "invariant"); assert(SafepointSynchronize::is_at_safepoint(), "invariant"); - assert_locked_or_safepoint(ClassLoaderDataGraph_lock); const traceid klass_id = JfrTraceId::load_raw(ik); const JfrInstrumentedClass jic(klass_id, ik, false); @@ -235,8 +228,9 @@ void JfrMethodTracer::on_klass_redefinition(const InstanceKlass* ik, Thread* thr assert(!JfrTraceIdEpoch::has_method_tracer_changed_tag_state(), "invariant"); JfrTraceIdEpoch::set_method_tracer_tag_state(); } - add_timing_entry(ik, klass_id); - JfrTraceTagging::set_dynamic_tag_for_sticky_bit(ik); + if (has_timing) { + add_timing_entry(klass_id); + } log_add(ik); } } @@ -258,8 +252,7 @@ void JfrMethodTracer::add_instrumented_class(InstanceKlass* ik, GrowableArraymodule()->add_read(jdk_jfr_module()); MutexLocker lock(ClassLoaderDataGraph_lock); assert(!in_instrumented_list(ik, instrumented_classes()), "invariant"); - JfrTraceTagging::set_dynamic_tag(ik, methods); - JfrTraceTagging::set_sticky_bit(ik, methods); + JfrTraceTagging::tag_sticky(ik, methods); const JfrInstrumentedClass jik(JfrTraceId::load_raw(ik), ik, false); const int idx = instrumented_classes()->append(jik); if (idx == 0) { diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp index 1c44a93fcb2..d67de9daa59 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrMethodTracer.hpp @@ -51,7 +51,7 @@ class JfrMethodTracer: AllStatic { static GrowableArray* _timing_entries; // Guarded by ClassLoaderDataGraph_lock static ModuleEntry* jdk_jfr_module(); - static void add_timing_entry(const InstanceKlass* ik, traceid klass_id); + static void add_timing_entry(traceid klass_id); static void retransform(JNIEnv* env, const JfrFilterClassClosure& classes, TRAPS); static void add_instrumented_class(InstanceKlass* ik, GrowableArray* methods); @@ -61,7 +61,7 @@ class JfrMethodTracer: AllStatic { static void add_to_unloaded_set(const Klass* k); static void trim_instrumented_classes(bool trim); static GrowableArray* instrumented_classes(); - static void on_klass_redefinition(const InstanceKlass* ik, Thread* thread); + static void on_klass_redefinition(const InstanceKlass* ik, bool has_timing); static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS); static jlongArray set_filters(JNIEnv* env, jobjectArray classes, diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp index e5018212768..dc70e70360f 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.cpp @@ -25,9 +25,11 @@ #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/support/methodtracer/jfrInstrumentedClass.hpp" +#include "jfr/support/methodtracer/jfrMethodTracer.hpp" #include "jfr/support/methodtracer/jfrTraceTagging.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" +#include "runtime/safepoint.hpp" #include "utilities/growableArray.hpp" void JfrTraceTagging::tag_dynamic(const InstanceKlass* ik) { @@ -38,100 +40,39 @@ void JfrTraceTagging::tag_dynamic(const Method* method) { JfrTraceId::load_no_enqueue(method); } -void JfrTraceTagging::tag_dynamic(const InstanceKlass* ik, const GrowableArray* methods) { - assert(ik != nullptr, "invariant"); - assert(methods != nullptr, "invariant"); - - for (int i = 0; i < methods->length(); ++i) { - const Method* const method = methods->at(i).method(); - assert(method != nullptr, "invariant"); - if (!method->is_old()) { - tag_dynamic(method); - continue; - } - // A redefinition / retransformation interleaved. - // Find and tag the latest version of the method. - tag_dynamic(ik->method_with_orig_idnum(method->orig_method_idnum())); - } -} - -void JfrTraceTagging::set_dynamic_tag(const InstanceKlass* ik, const GrowableArray* methods) { - assert(ik != nullptr, "invariant"); - assert(!ik->is_scratch_class(), "invariant"); - - tag_dynamic(ik, methods); - tag_dynamic(ik); -} - -void JfrTraceTagging::set_dynamic_tag_for_sticky_bit(const InstanceKlass* ik) { - assert(ik != nullptr, "invariant"); - assert(!ik->is_scratch_class(), "invariant"); - assert(JfrTraceId::has_sticky_bit(ik), "invariant"); - - const int length = ik->methods()->length(); - for (int i = 0; i < length; ++i) { - const Method* const m = ik->methods()->at(i); - if (JfrTraceId::has_sticky_bit(m)) { - tag_dynamic(m); - } - } - tag_dynamic(ik); -} - void JfrTraceTagging::tag_sticky(const InstanceKlass* ik) { JfrTraceId::set_sticky_bit(ik); } +void JfrTraceTagging::tag_sticky_enqueue(const InstanceKlass* ik) { + tag_sticky(ik); + JfrTraceIdLoadBarrier::enqueue(ik); +} + void JfrTraceTagging::tag_sticky(const Method* method) { JfrTraceId::set_sticky_bit(method); } -void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const GrowableArray* methods) { - assert(ik != nullptr, "invariant"); +void JfrTraceTagging::tag_sticky(const GrowableArray* methods) { assert(methods != nullptr, "invariant"); - + assert_locked_or_safepoint(ClassLoaderDataGraph_lock); for (int i = 0; i < methods->length(); ++i) { const Method* const method = methods->at(i).method(); assert(method != nullptr, "invariant"); - if (!method->is_old()) { - tag_sticky(method); - continue; - } - // A redefinition / retransformation interleaved. - // Find and tag the latest version of the method. - tag_sticky(ik->method_with_orig_idnum(method->orig_method_idnum())); + tag_sticky(method); } } -void JfrTraceTagging::tag_timing(const InstanceKlass* ik) { - JfrTraceId::set_timing_bit(ik); -} - -void JfrTraceTagging::install_sticky_bit_for_retransform_klass(const InstanceKlass* ik, const GrowableArray* methods, bool timing) { - assert(ik != nullptr, "invariant"); - assert(!ik->is_scratch_class(), "invariant"); - - MutexLocker lock(ClassLoaderDataGraph_lock); - if (JfrTraceId::has_sticky_bit(ik)) { - clear_sticky_bit(ik); - } - tag_sticky(ik, methods); - tag_sticky(ik); - if (timing) { - tag_timing(ik); - } -} - -void JfrTraceTagging::set_sticky_bit(const InstanceKlass* ik, const GrowableArray* methods) { +void JfrTraceTagging::tag_sticky(const InstanceKlass* ik, const GrowableArray* methods) { assert(ik != nullptr, "invariant"); assert(!ik->is_scratch_class(), "invariant"); + assert(methods != nullptr, "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock); - - tag_sticky(ik, methods); - tag_sticky(ik); + tag_sticky(methods); + tag_sticky_enqueue(ik); } -void JfrTraceTagging::clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag /* true */) { +void JfrTraceTagging::clear_sticky(const InstanceKlass* ik, bool dynamic_tag /* true */) { assert(ik != nullptr, "invariant"); assert(!ik->is_scratch_class(), "invariant"); assert(JfrTraceId::has_sticky_bit(ik), "invariant"); @@ -153,8 +94,78 @@ void JfrTraceTagging::clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag tag_dynamic(ik); } JfrTraceId::clear_sticky_bit(ik); - if (JfrTraceId::has_timing_bit(ik)) { - JfrTraceId::clear_timing_bit(ik); - } - assert(!JfrTraceId::has_timing_bit(ik), "invariant"); +} + +void JfrTraceTagging::tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray* methods, bool timing) { + assert(existing_klass != nullptr, "invariant"); + assert(scratch_klass != nullptr, "invariant"); + // The scratch class has not yet received its official status. + // assert(scratch_klass->is_scratch_class(), "invariant"); + if (timing) { + // Can be done outside lock because it is a scratch klass. + // Visibility guaranteed by upcoming safepoint. + JfrTraceId::set_timing_bit(scratch_klass); + } + MutexLocker lock(ClassLoaderDataGraph_lock); + if (JfrTraceId::has_sticky_bit(existing_klass)) { + clear_sticky(existing_klass); + } + tag_sticky(methods); + tag_sticky(existing_klass); +} + +void JfrTraceTagging::on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass) { + assert(ik != nullptr, "invariant"); + assert(ik->has_been_redefined(), "invariant"); + assert(scratch_klass != nullptr, "invariant"); + assert(scratch_klass->is_scratch_class(), "invariant"); + assert(SafepointSynchronize::is_at_safepoint(), "invariant"); + + const bool klass_has_sticky_bit = JfrTraceId::has_sticky_bit(ik); + if (klass_has_sticky_bit) { + JfrTraceIdLoadBarrier::enqueue(ik); + } + + const Array* new_methods = ik->methods(); + assert(new_methods != nullptr, "invariant"); + + const int len = new_methods->length(); // Can be shorter, equal to, or longer than old methods length. + + for (int i = 0; i < len; ++i) { + const Method* const nm = new_methods->at(i); + assert(nm != nullptr, "invariant"); + const Method* const om = scratch_klass->method_with_orig_idnum(nm->orig_method_idnum()); + if (om == nullptr) { + assert(AllowRedefinitionToAddDeleteMethods, "invariant"); + // nm is a newly added Method. + continue; + } + assert(nm != om, "invariant"); + assert(om->is_old(), "invariant"); + assert(nm->orig_method_idnum() == om->orig_method_idnum(), "invariant"); + assert(nm->name() == om->name() && nm->signature() == om->signature(), "invariant"); + + if (nm->trace_flags() == om->trace_flags()) { + continue; + } + + const bool is_blessed = IS_METHOD_BLESSED(nm); + + // Copy the old method trace flags under a safepoint. + nm->copy_trace_flags(om); + + assert(nm->trace_flags() == om->trace_flags(), "invariant"); + + if (is_blessed) { + BLESS_METHOD(nm); + assert(IS_METHOD_BLESSED(nm), "invariant"); + } + } + + // A retransformed/redefined klass carrying the sticky bit + // needs additional processing by the JfrMethodTracer subsystem. + if (klass_has_sticky_bit) { + assert(JfrMethodTracer::in_use(), "invariant"); + JfrMethodTracer::on_klass_redefinition(ik, JfrTraceId::has_timing_bit(scratch_klass)); + } } diff --git a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp index d2aa6f8bb04..38ead4d0fed 100644 --- a/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp +++ b/src/hotspot/share/jfr/support/methodtracer/jfrTraceTagging.hpp @@ -39,18 +39,16 @@ template class GrowableArray; class JfrTraceTagging : AllStatic { private: static void tag_dynamic(const InstanceKlass* ik); - static void tag_dynamic(const InstanceKlass* ik, const GrowableArray* methods); static void tag_dynamic(const Method* method); static void tag_sticky(const InstanceKlass* ik); static void tag_sticky(const Method* method); - static void tag_sticky(const InstanceKlass* ik, const GrowableArray* methods); - static void tag_timing(const InstanceKlass* ik); + static void tag_sticky(const GrowableArray* methods); + static void tag_sticky_enqueue(const InstanceKlass* ik); public: - static void set_dynamic_tag(const InstanceKlass* ik, const GrowableArray* methods); - static void set_dynamic_tag_for_sticky_bit(const InstanceKlass* ik); - static void install_sticky_bit_for_retransform_klass(const InstanceKlass* existing_klass, const GrowableArray* methods, bool timing); - static void set_sticky_bit(const InstanceKlass* ik, const GrowableArray* methods); - static void clear_sticky_bit(const InstanceKlass* ik, bool dynamic_tag = true); + static void clear_sticky(const InstanceKlass* ik, bool dynamic_tag = true); + static void tag_sticky(const InstanceKlass* ik, const GrowableArray* methods); + static void tag_sticky_for_retransform_klass(const InstanceKlass* existing_klass, const InstanceKlass* scratch_klass, const GrowableArray* methods, bool timing); + static void on_klass_redefinition(const InstanceKlass* ik, const InstanceKlass* scratch_klass); }; #endif /* SHARE_JFR_SUPPORT_METHODTRACER_JFRTRACETAGGING_HPP */ diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 305af6df9be..4257d7e997b 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -66,6 +66,9 @@ #include "utilities/checkedCast.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif Array* VM_RedefineClasses::_old_methods = nullptr; Array* VM_RedefineClasses::_new_methods = nullptr; @@ -1173,7 +1176,6 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( } } } - JFR_ONLY(k_new_method->copy_trace_flags(k_old_method->trace_flags());) log_trace(redefine, class, normalize) ("Method matched: new: %s [%d] == old: %s [%d]", k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi); @@ -4393,7 +4395,7 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas // keep track of previous versions of this class the_class->add_previous_version(scratch_class, emcp_method_count); - JFR_ONLY(ON_KLASS_REDEFINITION(the_class, current);) + JFR_ONLY(Jfr::on_klass_redefinition(the_class, scratch_class);) _timer_rsc_phase1.stop(); if (log_is_enabled(Info, redefine, class, timer)) { diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp index d4160161f19..84cc3fc316a 100644 --- a/src/hotspot/share/runtime/safepointMechanism.cpp +++ b/src/hotspot/share/runtime/safepointMechanism.cpp @@ -142,7 +142,6 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool ch do { JavaThreadState state = thread->thread_state(); guarantee(state == _thread_in_vm, "Illegal threadstate encountered: %d", state); - JFR_ONLY(Jfr::check_and_process_sample_request(thread);) if (global_poll()) { // Any load in ::block() must not pass the global poll load. // Otherwise we might load an old safepoint counter (for example). @@ -161,6 +160,7 @@ void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool ch need_rechecking = thread->handshake_state()->has_operation() && thread->handshake_state()->process_by_self(allow_suspend, check_async_exception); } while (need_rechecking); + JFR_ONLY(Jfr::check_and_process_sample_request(thread);) update_poll_values(thread); assert(sp_before == thread->last_Java_sp(), "Anchor has changed"); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java index daf6ad7278c..3b6859304b8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java @@ -77,7 +77,7 @@ final class ConstantMap { if (id != 0) { String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object"; Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg); - // assert false : msg; + assert false : msg; } return null; }