From 31eeef5e07c983ee8c37f63a5adeb7344d6fc5a5 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Wed, 25 Oct 2023 09:13:53 +0000 Subject: [PATCH] WIP --- src/hotspot/share/oops/klass.hpp | 1 + src/hotspot/share/oops/klass.inline.hpp | 5 +++++ src/hotspot/share/oops/method.cpp | 14 +++++++++++++- src/hotspot/share/oops/method.hpp | 10 ++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 9d15894a4905d..b46eea59b6536 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -682,6 +682,7 @@ class Klass : public Metadata { virtual MetaspaceObj::Type type() const { return ClassType; } inline bool is_loader_alive() const; + inline bool is_loader_alive_safe() const; void clean_subklass(); diff --git a/src/hotspot/share/oops/klass.inline.hpp b/src/hotspot/share/oops/klass.inline.hpp index af2480e149b45..7e4164025a959 100644 --- a/src/hotspot/share/oops/klass.inline.hpp +++ b/src/hotspot/share/oops/klass.inline.hpp @@ -52,6 +52,11 @@ inline bool Klass::is_loader_alive() const { return class_loader_data()->is_alive(); } +inline bool Klass::is_loader_alive_safe() const { + ClassLoaderData* cld = class_loader_data(); + return os::is_readable_pointer(cld) ? cld->is_alive() : false; +} + inline oop Klass::java_mirror() const { return _java_mirror.resolve(); } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 003f47b1e9c50..f8d21e197c4d6 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -125,6 +125,10 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, Symbol* name) { // Release Method*. The nmethod will be gone when we get here because // we've walked the code cache. void Method::deallocate_contents(ClassLoaderData* loader_data) { + // jmethodID mid = jmethod_id(); + // if (!(mid == nullptr || *((Method**)mid) == nullptr)){ + // fprintf(stdout, "!!! jmethodid not cleared out\n"); + // } MetadataFactory::free_metadata(loader_data, constMethod()); set_constMethod(nullptr); MetadataFactory::free_metadata(loader_data, method_data()); @@ -137,6 +141,10 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) { void Method::release_C_heap_structures() { if (method_data()) { + // jmethodID mid = jmethod_id(); + // if (!(mid == nullptr || *((Method**)mid) == nullptr)){ + // fprintf(stdout, "!!! jmethodid not cleared out\n"); + // } method_data()->release_C_heap_structures(); // Destroy MethodData embedded lock @@ -2231,12 +2239,16 @@ Method* Method::checked_resolve_jmethod_id(jmethodID mid) { if (o == nullptr || o == JNIMethodBlock::_free_method) { return nullptr; } + InstanceKlass* method_holder = o->method_holder_safe(); + if (method_holder == nullptr || !os::is_readable_pointer(method_holder)) { + return nullptr; + } // 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 : nullptr; + return method_holder->is_loader_alive_safe() ? o : nullptr; }; void Method::set_on_stack(const bool value) { diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 1dab585a66069..68f89732298ba 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -237,6 +237,11 @@ class Method : public Metadata { // constant pool for Klass* holding this method ConstantPool* constants() const { return constMethod()->constants(); } + // constant pool for Klass* holding this method or nullptr if it can't be accessed safely + ConstantPool* constants_safe() const { + ConstMethod* method = constMethod(); + return os::is_readable_pointer(method) ? method->constants() : nullptr; + } void set_constants(ConstantPool* c) { constMethod()->set_constants(c); } // max stack @@ -485,6 +490,11 @@ class Method : public Metadata { // method holder (the Klass* holding this method) InstanceKlass* method_holder() const { return constants()->pool_holder(); } + // method holder (the Klass* holding this method) or nullptr if can't be accessed safely + InstanceKlass* method_holder_safe() const { + ConstantPool* cp = constants_safe(); + return os::is_readable_pointer(cp) ? cp->pool_holder() : nullptr; + } Symbol* klass_name() const; // returns the name of the method holder BasicType result_type() const { return constMethod()->result_type(); }