src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp

Print this page
rev 4168 : 8005602: NPG: classunloading does not happen while CMS GC with -XX:+CMSClassUnloadingEnabled is used
Summary: Call purge() on CLDG after sweep(), reorder purge() call in GenCollectedHeap and enable some additional logging
Reviewed-by:

@@ -184,10 +184,16 @@
   CMSParGCThreadState(CompactibleFreeListSpace* cfls) : lab(cfls) {
     promo.setSpace(cfls);
   }
 };
 
+class CMSPhaseTracing: public StackObj {
+ public:
+  CMSPhaseTracing(bool print, const char* phase);
+  ~CMSPhaseTracing();
+};
+
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
      ReservedSpace rs, size_t initial_byte_size, int level,
      CardTableRS* ct, bool use_adaptive_freelists,
      FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
   CardGeneration(rs, initial_byte_size, level, ct),

@@ -2162,14 +2168,16 @@
     // Signal that we are about to start a collection
     gch->increment_total_full_collections();  // ... starting a collection cycle
     _collection_count_start = gch->total_full_collections();
   }
 
-  // Used for PrintGC
-  size_t prev_used;
-  if (PrintGC && Verbose) {
-    prev_used = _cmsGen->used(); // XXXPERM
+  // Used for PrintGCDetails
+  size_t prev_used = 0;
+  size_t metaspace_pre_unloading = 0;
+  if (PrintGCDetails) {
+    prev_used = _cmsGen->used();
+    metaspace_pre_unloading = MetaspaceAux::used_in_bytes();
   }
 
   // The change of the collection state is normally done at this level;
   // the exceptions are phases that are executed while the world is
   // stopped.  For those phases the change of state is done while the

@@ -2316,10 +2324,19 @@
           ReleaseForegroundGC x(this);   // unblock FG collection
           MutexLockerEx       y(Heap_lock, Mutex::_no_safepoint_check_flag);
           CMSTokenSync        z(true);   // not strictly needed.
           if (_collectorState == Resizing) {
             compute_new_size();
+            if (PrintGCDetails) {
+              CMSPhaseTracing pt(true, "[CMS-resizing: ");
+              gclog_or_tty->print("[%s:", cmsGen()->short_name());
+              cmsGen()->print_heap_change(prev_used);
+              gclog_or_tty->print("]");
+              MetaspaceAux::print_metaspace_change(metaspace_pre_unloading);
+              gclog_or_tty->print_cr(" ]");
+            }
+
             _collectorState = Resetting;
           } else {
             assert(_collectorState == Idling, "The state should only change"
                    " because the foreground collector has finished the collection");
           }

@@ -2369,13 +2386,10 @@
   if (TraceCMSState) {
     gclog_or_tty->print_cr("CMS Thread " INTPTR_FORMAT
       " exiting collection CMS state %d",
       Thread::current(), _collectorState);
   }
-  if (PrintGC && Verbose) {
-    _cmsGen->print_heap_change(prev_used);
-  }
 }
 
 void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
   assert(_foregroundGCIsActive && !_foregroundGCShouldWait,
          "Foreground collector should be waiting, not executing");

@@ -3362,14 +3376,23 @@
   // XXX Fix when compaction is implemented.
   warning("Shrinking of CMS not yet implemented");
   return;
 }
 
+CMSPhaseTracing::CMSPhaseTracing(bool print, const char* phase) {
+  if (print) {
+    gclog_or_tty->date_stamp(PrintGCDateStamps);
+    gclog_or_tty->stamp(PrintGCTimeStamps);
+    gclog_or_tty->print("%s", phase);
+  }
+}
+
+CMSPhaseTracing::~CMSPhaseTracing() {}
 
 // Simple ctor/dtor wrapper for accounting & timer chores around concurrent
 // phases.
-class CMSPhaseAccounting: public StackObj {
+class CMSPhaseAccounting: public CMSPhaseTracing {
  public:
   CMSPhaseAccounting(CMSCollector *collector,
                      const char *phase,
                      bool print_cr = true);
   ~CMSPhaseAccounting();

@@ -3393,19 +3416,18 @@
 };
 
 CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector,
                                        const char *phase,
                                        bool print_cr) :
+    CMSPhaseTracing(PrintGCDetails, ""),
   _collector(collector), _phase(phase), _print_cr(print_cr) {
 
   if (PrintCMSStatistics != 0) {
     _collector->resetYields();
   }
   if (PrintGCDetails && PrintGCTimeStamps) {
-    gclog_or_tty->date_stamp(PrintGCDateStamps);
-    gclog_or_tty->stamp();
-    gclog_or_tty->print_cr(": [%s-concurrent-%s-start]",
+    gclog_or_tty->print_cr("[%s-concurrent-%s-start]",
       _collector->cmsGen()->short_name(), _phase);
   }
   _collector->resetTimer();
   _wallclock.start();
   _collector->startTimer();

@@ -6071,10 +6093,14 @@
     _collectorState = Resizing;
   }
   verify_work_stacks_empty();
   verify_overflow_empty();
 
+  if (should_unload_classes()) {
+    ClassLoaderDataGraph::purge();
+  }
+
   _intra_sweep_timer.stop();
   _intra_sweep_estimate.sample(_intra_sweep_timer.seconds());
 
   _inter_sweep_timer.reset();
   _inter_sweep_timer.start();