8323883: JFR AssertionError: Missing object ID 15101
Reviewed-by: egahlin
This commit is contained in:
parent
61f249335d
commit
737b4c515e
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -36,6 +36,7 @@
|
|||||||
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
|
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
|
||||||
#include "jfr/recorder/service/jfrEventThrottler.hpp"
|
#include "jfr/recorder/service/jfrEventThrottler.hpp"
|
||||||
#include "jfr/recorder/service/jfrOptionSet.hpp"
|
#include "jfr/recorder/service/jfrOptionSet.hpp"
|
||||||
|
#include "jfr/recorder/service/jfrRecorderService.hpp"
|
||||||
#include "jfr/recorder/stacktrace/jfrStackFilter.hpp"
|
#include "jfr/recorder/stacktrace/jfrStackFilter.hpp"
|
||||||
#include "jfr/recorder/stacktrace/jfrStackFilterRegistry.hpp"
|
#include "jfr/recorder/stacktrace/jfrStackFilterRegistry.hpp"
|
||||||
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
|
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
|
||||||
@ -348,7 +349,8 @@ JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jclass jvm, jb
|
|||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
JVM_ENTRY_NO_ENV(void, jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean emit_all, jboolean skip_bfs))
|
JVM_ENTRY_NO_ENV(void, jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean emit_all, jboolean skip_bfs))
|
||||||
LeakProfiler::emit_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
|
JfrRecorderService service;
|
||||||
|
service.emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
JVM_ENTRY_NO_ENV(void, jfr_exclude_thread(JNIEnv* env, jclass jvm, jobject t))
|
JVM_ENTRY_NO_ENV(void, jfr_exclude_thread(JNIEnv* env, jclass jvm, jobject t))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -205,6 +205,15 @@ static bool stack_trace_precondition(const ObjectSample* sample) {
|
|||||||
return sample->has_stack_trace_id() && !sample->is_dead();
|
return sample->has_stack_trace_id() && !sample->is_dead();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_to_leakp_set(const ObjectSample* sample) {
|
||||||
|
assert(sample != nullptr, "invariant");
|
||||||
|
oop object = sample->object();
|
||||||
|
if (object == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JfrTraceId::load_leakp(object->klass());
|
||||||
|
}
|
||||||
|
|
||||||
class StackTraceBlobInstaller {
|
class StackTraceBlobInstaller {
|
||||||
private:
|
private:
|
||||||
BlobCache _cache;
|
BlobCache _cache;
|
||||||
@ -219,6 +228,7 @@ class StackTraceBlobInstaller {
|
|||||||
}
|
}
|
||||||
void sample_do(ObjectSample* sample) {
|
void sample_do(ObjectSample* sample) {
|
||||||
if (stack_trace_precondition(sample)) {
|
if (stack_trace_precondition(sample)) {
|
||||||
|
add_to_leakp_set(sample);
|
||||||
install(sample);
|
install(sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jfr/leakprofiler/sampling/objectSample.hpp"
|
#include "jfr/leakprofiler/sampling/objectSample.hpp"
|
||||||
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
|
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
|
||||||
|
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
|
||||||
#include "oops/weakHandle.inline.hpp"
|
#include "oops/weakHandle.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ void ObjectSample::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oop ObjectSample::object() const {
|
oop ObjectSample::object() const {
|
||||||
return _object.resolve();
|
return is_dead() ? nullptr :_object.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectSample::is_dead() const {
|
bool ObjectSample::is_dead() const {
|
||||||
@ -48,6 +49,7 @@ const oop* ObjectSample::object_addr() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ObjectSample::set_object(oop object) {
|
void ObjectSample::set_object(oop object) {
|
||||||
|
assert(object != nullptr, "invariant");
|
||||||
assert(_object.is_empty(), "should be empty");
|
assert(_object.is_empty(), "should be empty");
|
||||||
Handle h(Thread::current(), object);
|
Handle h(Thread::current(), object);
|
||||||
_object = WeakHandle(ObjectSampler::oop_storage(), h);
|
_object = WeakHandle(ObjectSampler::oop_storage(), h);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -126,7 +126,6 @@ static traceid artifact_tag(const T* ptr, bool leakp) {
|
|||||||
SET_LEAKP(ptr);
|
SET_LEAKP(ptr);
|
||||||
}
|
}
|
||||||
assert(IS_LEAKP(ptr), "invariant");
|
assert(IS_LEAKP(ptr), "invariant");
|
||||||
return artifact_id(ptr);
|
|
||||||
}
|
}
|
||||||
if (not_used(ptr)) {
|
if (not_used(ptr)) {
|
||||||
SET_TRANSIENT(ptr);
|
SET_TRANSIENT(ptr);
|
||||||
@ -153,7 +152,7 @@ static inline bool should_do_cld_klass(const Klass* cld_klass, bool leakp) {
|
|||||||
|
|
||||||
static inline bool should_enqueue(const Klass* cld_klass) {
|
static inline bool should_enqueue(const Klass* cld_klass) {
|
||||||
assert(cld_klass != nullptr, "invariant");
|
assert(cld_klass != nullptr, "invariant");
|
||||||
if (previous_epoch()) {
|
if (unloading() || previous_epoch()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CldPtr cld = get_cld(cld_klass);
|
CldPtr cld = get_cld(cld_klass);
|
||||||
@ -253,7 +252,11 @@ class ModuleFieldSelector {
|
|||||||
static TypePtr select(KlassPtr klass) {
|
static TypePtr select(KlassPtr klass) {
|
||||||
assert(klass != nullptr, "invariant");
|
assert(klass != nullptr, "invariant");
|
||||||
PkgPtr pkg = klass->package();
|
PkgPtr pkg = klass->package();
|
||||||
return pkg != nullptr ? pkg->module() : nullptr;
|
if (pkg == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
assert(current_epoch() ? IS_SERIALIZED(pkg) : true, "invariant");
|
||||||
|
return pkg->module();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -272,7 +275,11 @@ class ModuleCldFieldSelector {
|
|||||||
static TypePtr select(KlassPtr klass) {
|
static TypePtr select(KlassPtr klass) {
|
||||||
assert(klass != nullptr, "invariant");
|
assert(klass != nullptr, "invariant");
|
||||||
ModPtr mod = ModuleFieldSelector::select(klass);
|
ModPtr mod = ModuleFieldSelector::select(klass);
|
||||||
return mod != nullptr ? mod->loader_data() : nullptr;
|
if (mod == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
assert(current_epoch() ? IS_SERIALIZED(mod) : true, "invariant");
|
||||||
|
return mod->loader_data();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -283,18 +290,7 @@ class SerializePredicate {
|
|||||||
SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
|
SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
|
||||||
bool operator()(T const& value) {
|
bool operator()(T const& value) {
|
||||||
assert(value != nullptr, "invariant");
|
assert(value != nullptr, "invariant");
|
||||||
return _class_unload ? _artifacts->should_do_unloading_artifact(value) : IS_NOT_SERIALIZED(value);
|
return _class_unload ? true : IS_NOT_SERIALIZED(value);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class SerializePredicate<const Klass*> {
|
|
||||||
bool _class_unload;
|
|
||||||
public:
|
|
||||||
SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
|
|
||||||
bool operator()(const Klass* klass) {
|
|
||||||
assert(klass != nullptr, "invariant");
|
|
||||||
return _class_unload ? true : IS_NOT_SERIALIZED(klass);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -352,13 +348,19 @@ static void do_write_klass(JfrCheckpointWriter* writer, CldPtr cld, KlassPtr kla
|
|||||||
writer->write(package_id(klass, leakp));
|
writer->write(package_id(klass, leakp));
|
||||||
writer->write(klass->modifier_flags());
|
writer->write(klass->modifier_flags());
|
||||||
writer->write<bool>(klass->is_hidden());
|
writer->write<bool>(klass->is_hidden());
|
||||||
if (!leakp) {
|
if (leakp) {
|
||||||
set_serialized(klass);
|
assert(IS_LEAKP(klass), "invariant");
|
||||||
|
CLEAR_LEAKP(klass);
|
||||||
|
assert(IS_NOT_LEAKP(klass), "invariant");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
assert(used(klass), "invariant");
|
||||||
|
assert(unloading() ? true : IS_NOT_SERIALIZED(klass), "invariant");
|
||||||
|
set_serialized(klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool should_write_cld_klass(KlassPtr klass, bool leakp) {
|
static inline bool should_write_cld_klass(KlassPtr klass, bool leakp) {
|
||||||
return klass != nullptr && (leakp || IS_NOT_SERIALIZED(klass));
|
return klass != nullptr && (leakp ? IS_LEAKP(klass) : unloading() ? true : IS_NOT_SERIALIZED(klass));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp, int& elements) {
|
static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp, int& elements) {
|
||||||
@ -373,10 +375,10 @@ static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp,
|
|||||||
write_klass(writer, cld_klass, leakp, elements);
|
write_klass(writer, cld_klass, leakp, elements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KlassPtr mod_klass = get_module_cld_klass(klass, leakp);
|
KlassPtr mod_cld_klass = get_module_cld_klass(klass, leakp);
|
||||||
if (should_write_cld_klass(mod_klass, leakp)) {
|
if (should_write_cld_klass(mod_cld_klass, leakp)) {
|
||||||
// Write the klass for the module cld.
|
// Write the klass for the module cld.
|
||||||
write_klass(writer, mod_klass, leakp, elements);
|
write_klass(writer, mod_cld_klass, leakp, elements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +400,6 @@ int write__klass(JfrCheckpointWriter* writer, const void* k) {
|
|||||||
int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
|
int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
|
||||||
assert(k != nullptr, "invariant");
|
assert(k != nullptr, "invariant");
|
||||||
KlassPtr klass = static_cast<KlassPtr>(k);
|
KlassPtr klass = static_cast<KlassPtr>(k);
|
||||||
CLEAR_LEAKP(klass);
|
|
||||||
int elements = 0;
|
int elements = 0;
|
||||||
write_klass(writer, klass, true, elements);
|
write_klass(writer, klass, true, elements);
|
||||||
return elements;
|
return elements;
|
||||||
@ -978,15 +979,12 @@ class MethodIteratorHost {
|
|||||||
MethodUsedPredicate _method_used_predicate;
|
MethodUsedPredicate _method_used_predicate;
|
||||||
MethodFlagPredicate<leakp> _method_flag_predicate;
|
MethodFlagPredicate<leakp> _method_flag_predicate;
|
||||||
public:
|
public:
|
||||||
MethodIteratorHost(JfrCheckpointWriter* writer,
|
MethodIteratorHost(JfrCheckpointWriter* writer) :
|
||||||
bool current_epoch = false,
|
_method_cb(writer, unloading(), false),
|
||||||
bool class_unload = false,
|
_klass_cb(writer, unloading(), false),
|
||||||
bool skip_header = false) :
|
_klass_used_predicate(current_epoch()),
|
||||||
_method_cb(writer, class_unload, skip_header),
|
_method_used_predicate(current_epoch()),
|
||||||
_klass_cb(writer, class_unload, skip_header),
|
_method_flag_predicate(current_epoch()) {}
|
||||||
_klass_used_predicate(current_epoch),
|
|
||||||
_method_used_predicate(current_epoch),
|
|
||||||
_method_flag_predicate(current_epoch) {}
|
|
||||||
|
|
||||||
bool operator()(KlassPtr klass) {
|
bool operator()(KlassPtr klass) {
|
||||||
if (_method_used_predicate(klass)) {
|
if (_method_used_predicate(klass)) {
|
||||||
@ -1037,14 +1035,13 @@ typedef LeakPredicate<MethodPtr> LeakMethodPredicate;
|
|||||||
typedef JfrPredicatedTypeWriterImplHost<MethodPtr, LeakMethodPredicate, write__method__leakp> LeakMethodWriterImplTarget;
|
typedef JfrPredicatedTypeWriterImplHost<MethodPtr, LeakMethodPredicate, write__method__leakp> LeakMethodWriterImplTarget;
|
||||||
typedef JfrTypeWriterHost<LeakMethodWriterImplTarget, TYPE_METHOD> LeakMethodWriterImpl;
|
typedef JfrTypeWriterHost<LeakMethodWriterImplTarget, TYPE_METHOD> LeakMethodWriterImpl;
|
||||||
typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, true> LeakMethodWriter;
|
typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, true> LeakMethodWriter;
|
||||||
typedef MethodIteratorHost<LeakMethodWriterImpl, KlassCallbackStub, true> LeakMethodWriter;
|
|
||||||
typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
|
typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
|
||||||
|
|
||||||
static void write_methods_with_leakp(MethodWriter& mw) {
|
static void write_methods_with_leakp(MethodWriter& mw) {
|
||||||
assert(_writer != nullptr, "invariant");
|
assert(_writer != nullptr, "invariant");
|
||||||
assert(_leakp_writer != nullptr, "invariant");
|
assert(_leakp_writer != nullptr, "invariant");
|
||||||
assert(previous_epoch(), "invariant");
|
assert(previous_epoch(), "invariant");
|
||||||
LeakMethodWriter lpmw(_leakp_writer, current_epoch(), unloading());
|
LeakMethodWriter lpmw(_leakp_writer);
|
||||||
CompositeMethodWriter cmw(&lpmw, &mw);
|
CompositeMethodWriter cmw(&lpmw, &mw);
|
||||||
_artifacts->iterate_klasses(cmw);
|
_artifacts->iterate_klasses(cmw);
|
||||||
_artifacts->tally(mw);
|
_artifacts->tally(mw);
|
||||||
@ -1052,7 +1049,7 @@ static void write_methods_with_leakp(MethodWriter& mw) {
|
|||||||
|
|
||||||
static void write_methods() {
|
static void write_methods() {
|
||||||
assert(_writer != nullptr, "invariant");
|
assert(_writer != nullptr, "invariant");
|
||||||
MethodWriter mw(_writer, current_epoch(), unloading());
|
MethodWriter mw(_writer);
|
||||||
if (_leakp_writer == nullptr) {
|
if (_leakp_writer == nullptr) {
|
||||||
_artifacts->iterate_klasses(mw);
|
_artifacts->iterate_klasses(mw);
|
||||||
_artifacts->tally(mw);
|
_artifacts->tally(mw);
|
||||||
@ -1065,7 +1062,7 @@ static void write_methods_on_clear() {
|
|||||||
assert(_writer != nullptr, "invariant");
|
assert(_writer != nullptr, "invariant");
|
||||||
assert(_leakp_writer != nullptr, "invariant");
|
assert(_leakp_writer != nullptr, "invariant");
|
||||||
assert(previous_epoch(), "invariant");
|
assert(previous_epoch(), "invariant");
|
||||||
MethodWriter mw(_writer, current_epoch(), unloading());
|
MethodWriter mw(_writer);
|
||||||
write_methods_with_leakp(mw);
|
write_methods_with_leakp(mw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -54,10 +54,6 @@ void JfrArtifactSet::initialize(bool class_unload) {
|
|||||||
_klass_list = new GrowableArray<const Klass*>(initial_klass_list_size);
|
_klass_list = new GrowableArray<const Klass*>(initial_klass_list_size);
|
||||||
_klass_loader_set = new GrowableArray<const Klass*>(initial_klass_loader_set_size);
|
_klass_loader_set = new GrowableArray<const Klass*>(initial_klass_loader_set_size);
|
||||||
_klass_loader_leakp_set = new GrowableArray<const Klass*>(initial_klass_loader_set_size);
|
_klass_loader_leakp_set = new GrowableArray<const Klass*>(initial_klass_loader_set_size);
|
||||||
|
|
||||||
if (class_unload) {
|
|
||||||
_unloading_set = new GrowableArray<const Klass*>(initial_klass_list_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JfrArtifactSet::clear() {
|
void JfrArtifactSet::clear() {
|
||||||
@ -117,18 +113,9 @@ bool JfrArtifactSet::should_do_cld_klass(const Klass* k, bool leakp) {
|
|||||||
return not_in_set(leakp ? _klass_loader_leakp_set : _klass_loader_set, k);
|
return not_in_set(leakp ? _klass_loader_leakp_set : _klass_loader_set, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JfrArtifactSet::should_do_unloading_artifact(const void* ptr) {
|
|
||||||
assert(ptr != nullptr, "invariant");
|
|
||||||
assert(_class_unload, "invariant");
|
|
||||||
assert(_unloading_set != nullptr, "invariant");
|
|
||||||
// The incoming pointers are of all kinds of different types.
|
|
||||||
// However, we are only interested in set membership.
|
|
||||||
// Treat them uniformly as const Klass* for simplicity and code reuse.
|
|
||||||
return not_in_set(_unloading_set, static_cast<const Klass*>(ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void JfrArtifactSet::register_klass(const Klass* k) {
|
void JfrArtifactSet::register_klass(const Klass* k) {
|
||||||
assert(k != nullptr, "invariant");
|
assert(k != nullptr, "invariant");
|
||||||
|
assert(IS_SERIALIZED(k), "invariant");
|
||||||
assert(_klass_list != nullptr, "invariant");
|
assert(_klass_list != nullptr, "invariant");
|
||||||
_klass_list->append(k);
|
_klass_list->append(k);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -80,6 +80,7 @@ class KlassToFieldEnvelope {
|
|||||||
public:
|
public:
|
||||||
KlassToFieldEnvelope(Letter* letter) : _letter(letter) {}
|
KlassToFieldEnvelope(Letter* letter) : _letter(letter) {}
|
||||||
bool operator()(const Klass* klass) {
|
bool operator()(const Klass* klass) {
|
||||||
|
assert(IS_SERIALIZED(klass), "invariant");
|
||||||
typename FieldSelector::TypePtr t = FieldSelector::select(klass);
|
typename FieldSelector::TypePtr t = FieldSelector::select(klass);
|
||||||
return t != nullptr ? (*_letter)(t) : true;
|
return t != nullptr ? (*_letter)(t) : true;
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ class SymbolPredicate {
|
|||||||
|
|
||||||
class KlassUsedPredicate {
|
class KlassUsedPredicate {
|
||||||
bool _current_epoch;
|
bool _current_epoch;
|
||||||
public:
|
public:
|
||||||
KlassUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
|
KlassUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
|
||||||
bool operator()(const Klass* klass) {
|
bool operator()(const Klass* klass) {
|
||||||
return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass);
|
return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass);
|
||||||
@ -201,7 +202,6 @@ class JfrArtifactSet : public JfrCHeapObj {
|
|||||||
GrowableArray<const Klass*>* _klass_list;
|
GrowableArray<const Klass*>* _klass_list;
|
||||||
GrowableArray<const Klass*>* _klass_loader_set;
|
GrowableArray<const Klass*>* _klass_loader_set;
|
||||||
GrowableArray<const Klass*>* _klass_loader_leakp_set;
|
GrowableArray<const Klass*>* _klass_loader_leakp_set;
|
||||||
GrowableArray<const Klass*>* _unloading_set;
|
|
||||||
size_t _total_count;
|
size_t _total_count;
|
||||||
bool _class_unload;
|
bool _class_unload;
|
||||||
|
|
||||||
@ -229,23 +229,8 @@ class JfrArtifactSet : public JfrCHeapObj {
|
|||||||
size_t total_count() const;
|
size_t total_count() const;
|
||||||
void register_klass(const Klass* k);
|
void register_klass(const Klass* k);
|
||||||
bool should_do_cld_klass(const Klass* k, bool leakp);
|
bool should_do_cld_klass(const Klass* k, bool leakp);
|
||||||
bool should_do_unloading_artifact(const void* ptr);
|
|
||||||
void increment_checkpoint_id();
|
void increment_checkpoint_id();
|
||||||
|
|
||||||
template <typename Functor>
|
|
||||||
void iterate_klasses(Functor& functor) const {
|
|
||||||
for (int i = 0; i < _klass_list->length(); ++i) {
|
|
||||||
if (!functor(_klass_list->at(i))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < _klass_loader_set->length(); ++i) {
|
|
||||||
if (!functor(_klass_loader_set->at(i))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void iterate_symbols(T& functor) {
|
void iterate_symbols(T& functor) {
|
||||||
_symbol_table->iterate_symbols(functor);
|
_symbol_table->iterate_symbols(functor);
|
||||||
@ -261,6 +246,24 @@ class JfrArtifactSet : public JfrCHeapObj {
|
|||||||
_total_count += writer.count();
|
_total_count += writer.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Functor>
|
||||||
|
void iterate_klasses(Functor& functor) const {
|
||||||
|
if (iterate(functor, _klass_list)) {
|
||||||
|
iterate(functor, _klass_loader_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Functor>
|
||||||
|
bool iterate(Functor& functor, GrowableArray<const Klass*>* list) const {
|
||||||
|
assert(list != nullptr, "invariant");
|
||||||
|
for (int i = 0; i < list->length(); ++i) {
|
||||||
|
if (!functor(list->at(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class KlassArtifactRegistrator {
|
class KlassArtifactRegistrator {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -92,6 +92,7 @@ class JfrTraceId : public AllStatic {
|
|||||||
static traceid load(const ModuleEntry* module);
|
static traceid load(const ModuleEntry* module);
|
||||||
static traceid load(const PackageEntry* package);
|
static traceid load(const PackageEntry* package);
|
||||||
static traceid load(const ClassLoaderData* cld);
|
static traceid load(const ClassLoaderData* cld);
|
||||||
|
static traceid load_leakp(const Klass* klass); // leak profiler
|
||||||
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
|
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
|
||||||
static traceid load_leakp_previous_epoch(const Klass* klass, const Method* method); // leak profiler
|
static traceid load_leakp_previous_epoch(const Klass* klass, const Method* method); // leak profiler
|
||||||
static traceid load_no_enqueue(const Method* method);
|
static traceid load_no_enqueue(const Method* method);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -68,6 +68,10 @@ inline traceid JfrTraceId::load(const ClassLoaderData* cld) {
|
|||||||
return JfrTraceIdLoadBarrier::load(cld);
|
return JfrTraceIdLoadBarrier::load(cld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline traceid JfrTraceId::load_leakp(const Klass* klass) {
|
||||||
|
return JfrTraceIdLoadBarrier::load_leakp(klass);
|
||||||
|
}
|
||||||
|
|
||||||
inline traceid JfrTraceId::load_leakp(const Klass* klass, const Method* method) {
|
inline traceid JfrTraceId::load_leakp(const Klass* klass, const Method* method) {
|
||||||
return JfrTraceIdLoadBarrier::load_leakp(klass, method);
|
return JfrTraceIdLoadBarrier::load_leakp(klass, method);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -87,6 +87,7 @@ class JfrTraceIdLoadBarrier : AllStatic {
|
|||||||
static traceid load(const Method* method);
|
static traceid load(const Method* method);
|
||||||
static traceid load(const ModuleEntry* module);
|
static traceid load(const ModuleEntry* module);
|
||||||
static traceid load(const PackageEntry* package);
|
static traceid load(const PackageEntry* package);
|
||||||
|
static traceid load_leakp(const Klass* klass); // leak profiler
|
||||||
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
|
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
|
||||||
static traceid load_leakp_previuos_epoch(const Klass* klass, const Method* method); // leak profiler
|
static traceid load_leakp_previuos_epoch(const Klass* klass, const Method* method); // leak profiler
|
||||||
static void do_klasses(void f(Klass*), bool previous_epoch = false);
|
static void do_klasses(void f(Klass*), bool previous_epoch = false);
|
||||||
|
@ -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.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -82,7 +82,7 @@ inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) {
|
|||||||
if (should_tag(klass)) {
|
if (should_tag(klass)) {
|
||||||
load_barrier(klass);
|
load_barrier(klass);
|
||||||
}
|
}
|
||||||
assert(USED_THIS_EPOCH(klass), "invariant");
|
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
|
||||||
return TRACE_ID(klass);
|
return TRACE_ID(klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +148,13 @@ inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) {
|
|||||||
return set_used_and_get(package);
|
return set_used_and_get(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass) {
|
||||||
|
assert(klass != nullptr, "invariant");
|
||||||
|
load(klass); // Ensure tagged and enqueued.
|
||||||
|
SET_LEAKP(klass);
|
||||||
|
return TRACE_ID(klass);
|
||||||
|
}
|
||||||
|
|
||||||
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) {
|
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) {
|
||||||
assert(klass != nullptr, "invariant");
|
assert(klass != nullptr, "invariant");
|
||||||
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
|
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -691,3 +691,15 @@ void JfrRecorderService::evaluate_chunk_size_for_rotation() {
|
|||||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
|
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
|
||||||
JfrChunkRotation::evaluate(_chunkwriter);
|
JfrChunkRotation::evaluate(_chunkwriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs) {
|
||||||
|
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(JavaThread::current()));
|
||||||
|
// Take the rotation lock to exclude flush() during event emits. This is because event emit
|
||||||
|
// also creates a number checkpoint events. Those checkpoint events require a future typeset checkpoint
|
||||||
|
// event for completeness, i.e. to be generated before being flushed to a segment.
|
||||||
|
// The upcoming flush() or rotation() after event emit completes this typeset checkpoint
|
||||||
|
// and serializes all event emit checkpoint events to the same segment.
|
||||||
|
JfrRotationLock lock;
|
||||||
|
LeakProfiler::emit_events(cutoff_ticks, emit_all, skip_bfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -70,6 +70,7 @@ class JfrRecorderService : public StackObj {
|
|||||||
void flushpoint();
|
void flushpoint();
|
||||||
void process_full_buffers();
|
void process_full_buffers();
|
||||||
void evaluate_chunk_size_for_rotation();
|
void evaluate_chunk_size_for_rotation();
|
||||||
|
void emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs);
|
||||||
static bool is_recording();
|
static bool is_recording();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -95,6 +95,10 @@ class JfrTraceFlag {
|
|||||||
} \
|
} \
|
||||||
uint8_t* trace_meta_addr() const { \
|
uint8_t* trace_meta_addr() const { \
|
||||||
return _trace_flags.meta_addr(); \
|
return _trace_flags.meta_addr(); \
|
||||||
|
} \
|
||||||
|
void copy_trace_flags(uint8_t src_flags) const { \
|
||||||
|
uint8_t flags = *_trace_flags.flags_addr(); \
|
||||||
|
_trace_flags.set_flags(flags | src_flags); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
|
#endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "oops/fieldStreams.inline.hpp"
|
#include "oops/fieldStreams.inline.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
|
#include "oops/method.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/recordComponent.hpp"
|
#include "oops/recordComponent.hpp"
|
||||||
#include "prims/jvmtiImpl.hpp"
|
#include "prims/jvmtiImpl.hpp"
|
||||||
@ -64,6 +65,7 @@
|
|||||||
#include "utilities/bitMap.inline.hpp"
|
#include "utilities/bitMap.inline.hpp"
|
||||||
#include "utilities/checkedCast.hpp"
|
#include "utilities/checkedCast.hpp"
|
||||||
#include "utilities/events.hpp"
|
#include "utilities/events.hpp"
|
||||||
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
Array<Method*>* VM_RedefineClasses::_old_methods = nullptr;
|
Array<Method*>* VM_RedefineClasses::_old_methods = nullptr;
|
||||||
Array<Method*>* VM_RedefineClasses::_new_methods = nullptr;
|
Array<Method*>* VM_RedefineClasses::_new_methods = nullptr;
|
||||||
@ -1171,6 +1173,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JFR_ONLY(k_new_method->copy_trace_flags(*k_old_method->trace_flags_addr());)
|
||||||
log_trace(redefine, class, normalize)
|
log_trace(redefine, class, normalize)
|
||||||
("Method matched: new: %s [%d] == old: %s [%d]",
|
("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);
|
k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi);
|
||||||
|
@ -77,8 +77,7 @@ final class ConstantMap {
|
|||||||
if (id != 0) {
|
if (id != 0) {
|
||||||
String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object";
|
String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object";
|
||||||
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg);
|
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg);
|
||||||
// Disable assertion until JDK-8323883 is fixed
|
assert false : msg;
|
||||||
// assert false : msg;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user