8181170: resolved_references array leaks for RedefineClasses
authorcoleenp
Wed, 30 Aug 2017 07:18:02 -0400
changeset 47095 9d21da6fe729
parent 47093 5ee2be48e45e
child 47096 477158f58446
8181170: resolved_references array leaks for RedefineClasses Summary: clear out resolved_reference from ClassLoaderData::_handles Reviewed-by: stefank, jiangli, sspitsyn
hotspot/src/share/vm/classfile/classLoaderData.cpp
hotspot/src/share/vm/classfile/classLoaderData.hpp
hotspot/src/share/vm/oops/constantPool.cpp
hotspot/src/share/vm/oops/cpCache.cpp
hotspot/src/share/vm/oops/cpCache.hpp
hotspot/src/share/vm/oops/oopHandle.hpp
--- 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