src/hotspot/share/classfile/dictionary.cpp
changeset 48811 58787a1708d2
parent 48781 6ebef5cd0c8d
child 49329 04ed29f9ef33
--- a/src/hotspot/share/classfile/dictionary.cpp	Wed Jan 24 11:22:50 2018 +0100
+++ b/src/hotspot/share/classfile/dictionary.cpp	Wed Jan 24 11:33:18 2018 -0500
@@ -212,8 +212,44 @@
   }
 }
 
+// During class loading we may have cached a protection domain that has
+// since been unreferenced, so this entry should be cleared.
+void Dictionary::clean_cached_protection_domains(BoolObjectClosure* is_alive, DictionaryEntry* probe) {
+  assert_locked_or_safepoint(SystemDictionary_lock);
 
-void Dictionary::do_unloading() {
+  ProtectionDomainEntry* current = probe->pd_set();
+  ProtectionDomainEntry* prev = NULL;
+  while (current != NULL) {
+    if (!is_alive->do_object_b(current->object_no_keepalive())) {
+      LogTarget(Debug, protectiondomain) lt;
+      if (lt.is_enabled()) {
+        ResourceMark rm;
+        // Print out trace information
+        LogStream ls(lt);
+        ls.print_cr("PD in set is not alive:");
+        ls.print("class loader: "); loader_data()->class_loader()->print_value_on(&ls);
+        ls.print(" protection domain: "); current->object_no_keepalive()->print_value_on(&ls);
+        ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls);
+        ls.cr();
+      }
+      if (probe->pd_set() == current) {
+        probe->set_pd_set(current->next());
+      } else {
+        assert(prev != NULL, "should be set by alive entry");
+        prev->set_next(current->next());
+      }
+      ProtectionDomainEntry* to_delete = current;
+      current = current->next();
+      delete to_delete;
+    } else {
+      prev = current;
+      current = current->next();
+    }
+  }
+}
+
+
+void Dictionary::do_unloading(BoolObjectClosure* is_alive) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
   // The NULL class loader doesn't initiate loading classes from other class loaders
@@ -239,6 +275,8 @@
         free_entry(probe);
         continue;
       }
+      // Clean pd_set
+      clean_cached_protection_domains(is_alive, probe);
       p = probe->next_addr();
     }
   }
@@ -412,6 +450,10 @@
 
   entry->add_protection_domain(this, protection_domain);
 
+#ifdef ASSERT
+  assert(loader_data() != ClassLoaderData::the_null_class_loader_data(), "doesn't make sense");
+#endif
+
   assert(entry->contains_protection_domain(protection_domain()),
          "now protection domain should be present");
 }