8181170: resolved_references array leaks for RedefineClasses
Summary: clear out resolved_reference from ClassLoaderData::_handles
Reviewed-by: stefank, jiangli, sspitsyn
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Aug 30 07:18:02 2017 -0400
@@ -75,6 +75,9 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif // INCLUDE_ALL_GCS
#if INCLUDE_TRACE
#include "trace/tracing.hpp"
#endif
@@ -764,6 +767,25 @@
return OopHandle(_handles.add(h()));
}
+void ClassLoaderData::remove_handle(OopHandle h) {
+ oop* ptr = h.ptr_raw();
+ if (ptr != NULL) {
+ assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
+#if INCLUDE_ALL_GCS
+ // This barrier is used by G1 to remember the old oop values, so
+ // that we don't forget any objects that were live at the snapshot at
+ // the beginning.
+ if (UseG1GC) {
+ oop obj = *ptr;
+ if (obj != NULL) {
+ G1SATBCardTableModRefBS::enqueue(obj);
+ }
+ }
+#endif
+ *ptr = NULL;
+ }
+}
+
void ClassLoaderData::init_handle_locked(OopHandle& dest, Handle h) {
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
if (dest.resolve() != NULL) {
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Aug 30 07:18:02 2017 -0400
@@ -364,6 +364,7 @@
const char* loader_name();
OopHandle add_handle(Handle h);
+ void remove_handle(OopHandle h);
void init_handle_locked(OopHandle& pd, Handle h); // used for concurrent access to ModuleEntry::_pd field
void add_class(Klass* k, bool publicize = true);
void remove_class(Klass* k);
--- a/hotspot/src/share/vm/oops/constantPool.cpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Wed Aug 30 07:18:02 2017 -0400
@@ -89,8 +89,6 @@
void ConstantPool::deallocate_contents(ClassLoaderData* loader_data) {
if (cache() != NULL) {
- MetadataFactory::free_array<u2>(loader_data, reference_map());
- set_reference_map(NULL);
MetadataFactory::free_metadata(loader_data, cache());
set_cache(NULL);
}
--- a/hotspot/src/share/vm/oops/cpCache.cpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/oops/cpCache.cpp Wed Aug 30 07:18:02 2017 -0400
@@ -26,6 +26,7 @@
#include "interpreter/interpreter.hpp"
#include "interpreter/rewriter.hpp"
#include "logging/log.hpp"
+#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
@@ -608,6 +609,14 @@
}
}
+void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
+ assert(!is_shared(), "shared caches are not deallocated");
+ data->remove_handle(_resolved_references);
+ set_resolved_references(NULL);
+ MetadataFactory::free_array<u2>(data, _reference_map);
+ set_reference_map(NULL);
+}
+
#if INCLUDE_CDS_JAVA_HEAP
oop ConstantPoolCache::archived_references() {
assert(UseSharedSpaces, "UseSharedSpaces expected.");
--- a/hotspot/src/share/vm/oops/cpCache.hpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/oops/cpCache.hpp Wed Aug 30 07:18:02 2017 -0400
@@ -510,9 +510,9 @@
void dump_cache();
#endif // INCLUDE_JVMTI
- // Deallocate - no fields to deallocate
+ // RedefineClasses support
DEBUG_ONLY(bool on_stack() { return false; })
- void deallocate_contents(ClassLoaderData* data) {}
+ void deallocate_contents(ClassLoaderData* data);
bool is_klass() const { return false; }
// Printing
--- a/hotspot/src/share/vm/oops/oopHandle.hpp Tue Aug 29 12:17:02 2017 +0200
+++ b/hotspot/src/share/vm/oops/oopHandle.hpp Wed Aug 30 07:18:02 2017 -0400
@@ -46,6 +46,9 @@
OopHandle(oop* w) : _obj(w) {}
oop resolve() const { return (_obj == NULL) ? (oop)NULL : *_obj; }
+
+ // Used only for removing handle.
+ oop* ptr_raw() { return _obj; }
};
#endif // SHARE_VM_OOPS_OOPHANDLE_HPP