Skip to content

Commit

Permalink
8268364: jmethod clearing should be done during unloading
Browse files Browse the repository at this point in the history
Backport-of: 3d84398d128bb2eed6280ebbc3f57afb3b89908f
  • Loading branch information
krk authored and shipilev committed Sep 16, 2024
1 parent 22f82b9 commit 35c1ebc
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 16 deletions.
30 changes: 16 additions & 14 deletions src/hotspot/share/classfile/classLoaderData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,21 @@ void ClassLoaderData::unload() {
// after erroneous classes are released.
classes_do(InstanceKlass::unload_class);

// Method::clear_jmethod_ids only sets the jmethod_ids to NULL without
// releasing the memory for related JNIMethodBlocks and JNIMethodBlockNodes.
// This is done intentionally because native code (e.g. JVMTI agent) holding
// jmethod_ids may access them after the associated classes and class loader
// are unloaded. The Java Native Interface Specification says "method ID
// does not prevent the VM from unloading the class from which the ID has
// been derived. After the class is unloaded, the method or field ID becomes
// invalid". In real world usages, the native code may rely on jmethod_ids
// being NULL after class unloading. Hence, it is unsafe to free the memory
// from the VM side without knowing when native code is going to stop using
// them.
if (_jmethod_ids != NULL) {
Method::clear_jmethod_ids(this);
}

// Clean up global class iterator for compiler
ClassLoaderDataGraph::adjust_saved_class(this);
}
Expand Down Expand Up @@ -696,20 +711,7 @@ ClassLoaderData::~ClassLoaderData() {
_metaspace = NULL;
delete m;
}
// Method::clear_jmethod_ids only sets the jmethod_ids to NULL without
// releasing the memory for related JNIMethodBlocks and JNIMethodBlockNodes.
// This is done intentionally because native code (e.g. JVMTI agent) holding
// jmethod_ids may access them after the associated classes and class loader
// are unloaded. The Java Native Interface Specification says "method ID
// does not prevent the VM from unloading the class from which the ID has
// been derived. After the class is unloaded, the method or field ID becomes
// invalid". In real world usages, the native code may rely on jmethod_ids
// being NULL after class unloading. Hence, it is unsafe to free the memory
// from the VM side without knowing when native code is going to stop using
// them.
if (_jmethod_ids != NULL) {
Method::clear_jmethod_ids(this);
}

// Delete lock
delete _metaspace_lock;

Expand Down
9 changes: 7 additions & 2 deletions src/hotspot/share/oops/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2242,10 +2242,15 @@ bool Method::is_method_id(jmethodID mid) {
Method* Method::checked_resolve_jmethod_id(jmethodID mid) {
if (mid == NULL) return NULL;
Method* o = resolve_jmethod_id(mid);
if (o == NULL || o == JNIMethodBlock::_free_method || !((Metadata*)o)->is_method()) {
if (o == NULL || o == JNIMethodBlock::_free_method) {
return NULL;
}
return o;
// Method should otherwise be valid. Assert for testing.
assert(is_valid_method(o), "should be valid jmethodid");
// If the method's class holder object is unreferenced, but not yet marked as
// unloaded, we need to return NULL here too because after a safepoint, its memory
// will be reclaimed.
return o->method_holder()->is_loader_alive() ? o : NULL;
};

void Method::set_on_stack(const bool value) {
Expand Down

1 comment on commit 35c1ebc

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.