diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 8c906fdb416..b0fbb17a7ae 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1036,7 +1036,6 @@ CodeCache::UnloadingScope::UnloadingScope(BoolObjectClosure* is_alive) CodeCache::UnloadingScope::~UnloadingScope() { IsUnloadingBehaviour::set_current(_saved_behaviour); DependencyContext::cleaning_end(); - CodeCache::flush_unlinked_nmethods(); } void CodeCache::verify_oops() { diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 8abc4043ae6..459df9b19f0 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -179,10 +179,7 @@ class CodeCache : AllStatic { // GC support static void verify_oops(); - // If any oops are not marked this method unloads (i.e., breaks root links - // to) any unmarked codeBlobs in the cache. Sets "marked_for_unloading" - // to "true" iff some code got unloaded. - // "unloading_occurred" controls whether metadata should be cleaned because of class unloading. + // Scope object managing code cache unloading behavior. class UnloadingScope: StackObj { ClosureIsUnloadingBehaviour _is_unloading_behaviour; IsUnloadingBehaviour* _saved_behaviour; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 14ec4bf385b..da0e058cc32 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1694,9 +1694,12 @@ void G1ConcurrentMark::weak_refs_work() { // Unload Klasses, String, Code Cache, etc. if (ClassUnloadingWithConcurrentMark) { GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm); - CodeCache::UnloadingScope scope(&g1_is_alive); - bool purged_classes = SystemDictionary::do_unloading(_gc_timer_cm); - _g1h->complete_cleaning(purged_classes); + { + CodeCache::UnloadingScope scope(&g1_is_alive); + bool unloading_occurred = SystemDictionary::do_unloading(_gc_timer_cm); + _g1h->complete_cleaning(unloading_occurred); + } + CodeCache::flush_unlinked_nmethods(); } } diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp index 4381d515c6a..f225937a49f 100644 --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -319,10 +319,13 @@ void G1FullCollector::phase1_mark_live_objects() { // Class unloading and cleanup. if (ClassUnloading) { GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer()); - CodeCache::UnloadingScope unloading_scope(&_is_alive); - // Unload classes and purge the SystemDictionary. - bool purged_class = SystemDictionary::do_unloading(scope()->timer()); - _heap->complete_cleaning(purged_class); + { + CodeCache::UnloadingScope unloading_scope(&_is_alive); + // Unload classes and purge the SystemDictionary. + bool unloading_occurred = SystemDictionary::do_unloading(scope()->timer()); + _heap->complete_cleaning(unloading_occurred); + } + CodeCache::flush_unlinked_nmethods(); } { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index d0839cf576b..637a7d3955c 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -2052,19 +2052,26 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { { GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", &_gc_timer); - CodeCache::UnloadingScope scope(is_alive_closure()); - // Follow system dictionary roots and unload classes. - bool purged_class = SystemDictionary::do_unloading(&_gc_timer); + bool unloading_occurred; + { + CodeCache::UnloadingScope scope(is_alive_closure()); - // Unload nmethods. - CodeCache::do_unloading(purged_class); + // Follow system dictionary roots and unload classes. + unloading_occurred = SystemDictionary::do_unloading(&_gc_timer); + + // Unload nmethods. + CodeCache::do_unloading(unloading_occurred); + } + + // Release unloaded nmethods's memory. + CodeCache::flush_unlinked_nmethods(); // Prune dead klasses from subklass/sibling/implementor lists. - Klass::clean_weak_klass_links(purged_class); + Klass::clean_weak_klass_links(unloading_occurred); // Clean JVMCI metadata handles. - JVMCI_ONLY(JVMCI::do_unloading(purged_class)); + JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred)); } { diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index 6200a1894f5..3228493b848 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -199,19 +199,26 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { { GCTraceTime(Debug, gc, phases) tm_m("Class Unloading", gc_timer()); - CodeCache::UnloadingScope scope(&is_alive); - // Unload classes and purge the SystemDictionary. - bool purged_class = SystemDictionary::do_unloading(gc_timer()); + bool unloading_occurred; + { + CodeCache::UnloadingScope scope(&is_alive); - // Unload nmethods. - CodeCache::do_unloading(purged_class); + // Unload classes and purge the SystemDictionary. + unloading_occurred = SystemDictionary::do_unloading(gc_timer()); + + // Unload nmethods. + CodeCache::do_unloading(unloading_occurred); + } + + // Release unloaded nmethod's memory. + CodeCache::flush_unlinked_nmethods(); // Prune dead klasses from subklass/sibling/implementor lists. - Klass::clean_weak_klass_links(purged_class); + Klass::clean_weak_klass_links(unloading_occurred); // Clean JVMCI metadata handles. - JVMCI_ONLY(JVMCI::do_unloading(purged_class)); + JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred)); } { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 75c2528b46e..3e266cd9b4d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1811,14 +1811,18 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) { ShenandoahPhaseTimings::full_gc_purge_class_unload : ShenandoahPhaseTimings::degen_gc_purge_class_unload; ShenandoahIsAliveSelector is_alive; - CodeCache::UnloadingScope scope(is_alive.is_alive_closure()); - ShenandoahGCPhase gc_phase(phase); - ShenandoahGCWorkerPhase worker_phase(phase); - bool purged_class = SystemDictionary::do_unloading(gc_timer()); + { + CodeCache::UnloadingScope scope(is_alive.is_alive_closure()); + ShenandoahGCPhase gc_phase(phase); + ShenandoahGCWorkerPhase worker_phase(phase); + bool unloading_occurred = SystemDictionary::do_unloading(gc_timer()); - uint num_workers = _workers->active_workers(); - ShenandoahClassUnloadingTask unlink_task(phase, num_workers, purged_class); - _workers->run_task(&unlink_task); + uint num_workers = _workers->active_workers(); + ShenandoahClassUnloadingTask unlink_task(phase, num_workers, unloading_occurred); + _workers->run_task(&unlink_task); + } + // Release unloaded nmethods's memory. + CodeCache::flush_unlinked_nmethods(); } {