void CardTableRS::invalidate_or_clear(Generation* gen, bool younger, bool perm) { GenCollectedHeap* gch = GenCollectedHeap::heap(); // For each generation gen (and younger and/or perm) // invalidate the cards for the currently occupied part // of that generation and clear the cards for the // unoccupied part of the generation (if any, making use // of that generation's prev_used_region to determine that // region). No need to do anything for the youngest // generation. Also see note#20040107.ysr above. Generation* g = gen; for(Generation* prev_gen = gch->prev_gen(g); prev_gen != NULL; g = prev_gen, prev_gen = gch->prev_gen(g)) { MemRegion used_mr = g->used_region(); MemRegion to_be_cleared_mr = g->prev_used_region().minus(used_mr); if (!to_be_cleared_mr.is_empty()) { clear(to_be_cleared_mr); } invalidate(used_mr); if (!younger) break; } // Clear perm gen cards if asked to do so. if (perm) { g = gch->perm_gen(); MemRegion used_mr = g->used_region(); MemRegion to_be_cleared_mr = g->prev_used_region().minus(used_mr); if (!to_be_cleared_mr.is_empty()) { clear(to_be_cleared_mr); } invalidate(used_mr); } }
void CardTableRS::clear_into_younger(Generation* gen, bool clear_perm) { GenCollectedHeap* gch = GenCollectedHeap::heap(); // Generations younger than gen have been evacuated. We can clear // card table entries for gen (we know that it has no pointers // to younger gens) and for those below. The card tables for // the youngest gen need never be cleared, and those for perm gen // will be cleared based on the parameter clear_perm. // There's a bit of subtlety in the clear() and invalidate() // methods that we exploit here and in invalidate_or_clear() // below to avoid missing cards at the fringes. If clear() or // invalidate() are changed in the future, this code should // be revisited. 20040107.ysr Generation* g = gen; for(Generation* prev_gen = gch->prev_gen(g); prev_gen != NULL; g = prev_gen, prev_gen = gch->prev_gen(g)) { MemRegion to_be_cleared_mr = g->prev_used_region(); clear(to_be_cleared_mr); } // Clear perm gen cards if asked to do so. if (clear_perm) { MemRegion to_be_cleared_mr = gch->perm_gen()->prev_used_region(); clear(to_be_cleared_mr); } }
void HeapInspection::heap_inspection() { ResourceMark rm; HeapWord* permgen_bottom = NULL; if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->gc_prologue(false /* !full */); // get any necessary locks permgen_bottom = gch->perm_gen()->used_region().start(); } else { return; } // Collect klass instance info // Iterate over objects in the heap KlassInfoTable cit(KlassInfoTable::cit_size, permgen_bottom); RecordInstanceClosure ric(&cit); Universe::heap()->object_iterate(&ric); // Sort and print klass instance info KlassInfoHisto histo("\n" "num #instances #bytes class name\n" "--------------------------------------", KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); histo.print_on(gclog_or_tty); gclog_or_tty->flush(); if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->gc_epilogue(false /* !full */); // release all acquired locks } }
/** * 标记清除的方式回收内存堆的垃圾对象 * 1.第一步: 标记所有存活的对象 * 2.第二步: 计算存活的对象在其内存区压缩后的偏移位置 * 3.第三步: 遍历所有存活的对象并修改其对应的地址映射表 * 4.第四步: 移动存活的对象压缩内存区 */ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, bool clear_all_softrefs) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); GenCollectedHeap* gch = GenCollectedHeap::heap(); #ifdef ASSERT if (gch->collector_policy()->should_clear_all_soft_refs()) { assert(clear_all_softrefs, "Policy should have been checked earlier"); } #endif // hook up weak ref data so it can be used during Mark-Sweep assert(ref_processor() == NULL, "no stomping"); assert(rp != NULL, "should be non-NULL"); _ref_processor = rp; rp->setup_policy(clear_all_softrefs); TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty); // When collecting the permanent generation methodOops may be moving, // so we either have to flush all bcp data or convert it into bci. CodeCache::gc_prologue(); Threads::gc_prologue(); // Increment the invocation count for the permanent generation, since it is // implicitly collected whenever we do a full mark sweep collection. gch->perm_gen()->stat_record()->invocations++; //本次Gc之前内存堆的使用量 size_t gch_prev_used = gch->used(); // Some of the card table updates below assume that the perm gen is // also being collected. assert(level == gch->n_gens() - 1, "All generations are being collected, ergo perm gen too."); // Capture used regions for each generation that will be // subject to collection, so that card table adjustments can // be made intelligently (see clear / invalidate further below). gch->save_used_regions(level, true /* perm */); allocate_stacks(); mark_sweep_phase1(level, clear_all_softrefs); mark_sweep_phase2(); // Don't add any more derived pointers during phase3 COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity")); COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); mark_sweep_phase3(level); VALIDATE_MARK_SWEEP_ONLY( if (ValidateMarkSweep) { guarantee(_root_refs_stack->length() == 0, "should be empty by now"); } )
static void print_contents() { if (PrintSharedSpaces) { GenCollectedHeap* gch = GenCollectedHeap::heap(); CompactingPermGenGen* gen = (CompactingPermGenGen*)gch->perm_gen(); // High level summary of the read-only space: ClassifyObjectClosure coc; tty->cr(); tty->print_cr("ReadOnly space:"); gen->ro_space()->object_iterate(&coc); coc.print(); // High level summary of the read-write space: coc.reset(); tty->cr(); tty->print_cr("ReadWrite space:"); gen->rw_space()->object_iterate(&coc); coc.print(); // Reset counters ClearAllocCountClosure cacc; gen->ro_space()->object_iterate(&cacc); gen->rw_space()->object_iterate(&cacc); coc.reset(); // Lower level summary of the read-only space: gen->ro_space()->object_iterate(&coc); tty->cr(); tty->print_cr("ReadOnly space:"); ClassifyInstanceKlassClosure cikc; gen->rw_space()->object_iterate(&cikc); cikc.print(); // Reset counters gen->ro_space()->object_iterate(&cacc); gen->rw_space()->object_iterate(&cacc); coc.reset(); // Lower level summary of the read-write space: gen->rw_space()->object_iterate(&coc); cikc.reset(); tty->cr(); tty->print_cr("ReadWrite space:"); gen->rw_space()->object_iterate(&cikc); cikc.print(); } }
void CompactingPermGenGen::serialize_oops(SerializeOopClosure* soc) { int tag = 0; soc->do_tag(--tag); assert(!UseCompressedOops, "UseCompressedOops doesn't work with shared archive"); // Verify the sizes of various oops in the system. soc->do_tag(sizeof(oopDesc)); soc->do_tag(sizeof(instanceOopDesc)); soc->do_tag(sizeof(methodOopDesc)); soc->do_tag(sizeof(constMethodOopDesc)); soc->do_tag(sizeof(methodDataOopDesc)); soc->do_tag(arrayOopDesc::base_offset_in_bytes(T_BYTE)); soc->do_tag(sizeof(constantPoolOopDesc)); soc->do_tag(sizeof(constantPoolCacheOopDesc)); soc->do_tag(objArrayOopDesc::base_offset_in_bytes()); soc->do_tag(typeArrayOopDesc::base_offset_in_bytes(T_BYTE)); soc->do_tag(sizeof(symbolOopDesc)); soc->do_tag(sizeof(klassOopDesc)); soc->do_tag(sizeof(markOopDesc)); soc->do_tag(sizeof(compiledICHolderOopDesc)); // Dump the block offset table entries. GenCollectedHeap* gch = GenCollectedHeap::heap(); CompactingPermGenGen* pg = (CompactingPermGenGen*)gch->perm_gen(); pg->serialize_bts(soc); soc->do_tag(--tag); pg->ro_space()->serialize_block_offset_array_offsets(soc); soc->do_tag(--tag); pg->rw_space()->serialize_block_offset_array_offsets(soc); soc->do_tag(--tag); // Special case - this oop needed in oop->is_oop() assertions. soc->do_ptr((void**)&Universe::_klassKlassObj); soc->do_tag(--tag); // Dump/restore miscellaneous oops. Universe::oops_do(soc, true); soc->do_tag(--tag); vmSymbols::oops_do(soc, true); soc->do_tag(--tag); CodeCache::oops_do(soc); soc->do_tag(--tag); soc->do_tag(666); }