From 08b0f4f6acd1272df1d928248da0669f34f9357c Mon Sep 17 00:00:00 2001 From: shshahma Date: Fri, 5 Aug 2016 10:47:35 +0000 Subject: [PATCH] 8161144: Fix for JDK-8147451 failed: Crash in Method::checked_resolve_jmethod_id(_jmethodID*) Summary: Method::deallocate_contents() should clear 'this' from list of Methods in JNIMethodBlock, when class is unloaded. Reviewed-by: coleenp, dholmes --- src/share/vm/oops/method.cpp | 20 +++++++++++++++++++- src/share/vm/oops/method.hpp | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/share/vm/oops/method.cpp b/src/share/vm/oops/method.cpp index 4a05a727d..b1db4dc00 100644 --- a/src/share/vm/oops/method.cpp +++ b/src/share/vm/oops/method.cpp @@ -111,6 +111,7 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) { // 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) { + clear_jmethod_id(loader_data); MetadataFactory::free_metadata(loader_data, constMethod()); set_constMethod(NULL); MetadataFactory::free_metadata(loader_data, method_data()); @@ -1800,6 +1801,17 @@ class JNIMethodBlock : public CHeapObj { #endif // ASSERT *m = _free_method; } + void clear_method(Method* m) { + for (JNIMethodBlock* b = this; b != NULL; b = b->_next) { + for (int i = 0; i < number_of_methods; i++) { + if (b->_methods[i] == m) { + b->_methods[i] = NULL; + return; + } + } + } + // not found + } // During class unloading the methods are cleared, which is different // than freed. @@ -1872,7 +1884,9 @@ void Method::change_method_associated_with_jmethod_id(jmethodID jmid, Method* ne bool Method::is_method_id(jmethodID mid) { Method* m = resolve_jmethod_id(mid); - assert(m != NULL, "should be called with non-null method"); + if (m == NULL) { + return false; + } InstanceKlass* ik = m->method_holder(); if (ik == NULL) { return false; @@ -1905,6 +1919,10 @@ void Method::set_on_stack(const bool value) { } } +void Method::clear_jmethod_id(ClassLoaderData* loader_data) { + loader_data->jmethod_ids()->clear_method(this); +} + // Called when the class loader is unloaded to make all methods weak. void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { loader_data->jmethod_ids()->clear_all_methods(); diff --git a/src/share/vm/oops/method.hpp b/src/share/vm/oops/method.hpp index 212603363..974bced59 100644 --- a/src/share/vm/oops/method.hpp +++ b/src/share/vm/oops/method.hpp @@ -768,6 +768,8 @@ class Method : public Metadata { // Helper routines for intrinsic_id() and vmIntrinsics::method(). void init_intrinsic_id(); // updates from _none if a match + void clear_jmethod_id(ClassLoaderData* loader_data); + static vmSymbols::SID klass_id_for_intrinsics(Klass* holder); bool jfr_towrite() { return _jfr_towrite; } -- GitLab