In DefNewGeneration::collect()
,
FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
&fsc_with_no_gc_barrier,
&fsc_with_gc_barrier);
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
gch->gen_process_strong_roots(_level,
true, // Process younger gens, if any,
// as strong roots.
true, // activate StrongRootsScope
false, // not collecting perm generation.
SharedHeap::SO_AllClasses,
&fsc_with_no_gc_barrier,
true, // walk *all* scavengable nmethods
&fsc_with_gc_barrier);
// "evacuate followers".
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
ReferenceProcessor* rp = ref_processor();
rp->setup_policy(clear_all_soft_refs);
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
NULL);
The stack trace we got from this example is in a "evacuate followers" phase, with evacuate_followers.do_void()
void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
do {
_gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap,
_scan_older);
} while (!_gch->no_allocs_since_save_marks(_level));
guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
}
// Apply "blk->do_oop" to the addresses of all reference fields in objects
// starting with the _saved_mark_word, which was noted during a generation's
// save_marks and is required to denote the head of an object.
// Fields in objects allocated by applications of the closure
// *are* included in the iteration.
// Updates _saved_mark_word to point to just after the last object
// iterated over.
#define ContigSpace_OOP_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \
void oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk);
ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DECL)
#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DECL
#define ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \
\
void ContiguousSpace:: \
oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \
HeapWord* t; \
HeapWord* p = saved_mark_word(); \
assert(p != NULL, "expected saved mark"); \
\
const intx interval = PrefetchScanIntervalInBytes; \
do { \
t = top(); \
while (p < t) { \
Prefetch::write(p, interval); \
debug_only(HeapWord* prev = p); \
oop m = oop(p); \
p += m->oop_iterate(blk); \
} \
} while (t < top()); \
\
set_saved_mark_word(p); \
}
ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN)
#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN
and coming down to the following code when scanning through a weakref instance
#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \
if (closure->apply_to_weak_ref_discovered_field()) { \
T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \
closure->do_oop##nv_suffix(disc_addr); \
} \
\
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \
T heap_oop = oopDesc::load_heap_oop(referent_addr); \
if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) { \
ReferenceProcessor* rp = closure->_ref_processor; \
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \
if (!referent->is_gc_marked() && (rp != NULL) && \
rp->discover_reference(obj, reference_type())) { \
return size; \
} else { \
/* treat referent as normal oop */ \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
closure->do_oop##nv_suffix(referent_addr); \
} \
} \
/* treat next as normal oop */ \
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \
if (contains(next_addr)) { \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
closure->do_oop##nv_suffix(next_addr); \
} \
return size; \
Promoted sun.misc.Cleaner
s are recorded in the card table during reference processing.
template <class T>
inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
{
// We never expect to see a null reference being processed
// as a weak reference.
assert (!oopDesc::is_null(*p), "expected non-null ref");
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
assert (obj->is_oop(), "expected an oop while scanning weak refs");
}
#endif // ASSERT
_cl->do_oop_nv(p);
// Card marking is trickier for weak refs.
// This oop is a 'next' field which was filled in while we
// were discovering weak references. While we might not need
// to take a special action to keep this reference alive, we
// will need to dirty a card as the field was modified.
//
// Alternatively, we could create a method which iterates through
// each generation, allowing them in turn to examine the modified
// field.
//
// We could check that p is also in an older generation, but
// dirty cards in the youngest gen are never scanned, so the
// extra check probably isn't worthwhile.
if (Universe::heap()->is_in_reserved(p)) {
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
_rs->inline_write_ref_field_gc(p, obj);
}
}
template <class T>
inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
{
// We never expect to see a null reference being processed
// as a weak reference.
assert (!oopDesc::is_null(*p), "expected non-null ref");
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
assert (obj->is_oop(), "expected an oop while scanning weak refs");
}
#endif // ASSERT
_cl->do_oop_nv(p);
// Optimized for Defnew generation if it's the youngest generation:
// we set a younger_gen card if we have an older->youngest
// generation pointer.
oop obj = oopDesc::load_decode_heap_oop_not_null(p);
if (((HeapWord*)obj < _boundary) && Universe::heap()->is_in_reserved(p)) {
_rs->inline_write_ref_field_gc(p, obj);
}
}
So in the second young GC in this example, the sun.misc.Cleaner
s in the old generation are scanned, but not processed, as shown in the following log:
sun.misc.Cleaner @ 0x00000000f0589fd8 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xbbbb50] print_stack_trace_on(outputStream*)+0x20
V [libjvm.so+0xbbe6bb] ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V [libjvm.so+0x7bec94] instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FilteringClosure*)+0x1e4
V [libjvm.so+0xc2f0fe] ContiguousSpaceDCTOC::walk_mem_region_with_cl(MemRegion, HeapWord*, HeapWord*, FilteringClosure*)+0x16e
V [libjvm.so+0xc29359] Filtering_DCTOC::walk_mem_region(MemRegion, HeapWord*, HeapWord*)+0x89
V [libjvm.so+0xc2a7b8] DirtyCardToOopClosure::do_MemRegion(MemRegion)+0x1a8
V [libjvm.so+0x4c2dc8] ClearNoncleanCardWrapper::do_MemRegion(MemRegion)+0x2d8
V [libjvm.so+0x4bf694] CardTableModRefBS::non_clean_card_iterate_work(MemRegion, MemRegionClosure*, bool)+0x3f4
V [libjvm.so+0x4bf7e2] CardTableModRefBS::non_clean_card_iterate(Space*, MemRegion, DirtyCardToOopClosure*, MemRegionClosure*, bool)+0x72
V [libjvm.so+0x4c11af] CardTableRS::younger_refs_in_space_iterate(Space*, OopsInGenClosure*)+0x8f
V [libjvm.so+0x741e70] OneContigSpaceCardGeneration::younger_refs_iterate(OopsInGenClosure*)+0x40
V [libjvm.so+0x72f326] GenCollectedHeap::gen_process_strong_roots(int, bool, bool, bool, SharedHeap::ScanningOption, OopsInGenClosure*, bool, OopsInGenClosure*)+0xc6
V [libjvm.so+0x6493c3] DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x253
V [libjvm.so+0x73002c] GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V [libjvm.so+0x57e567] GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V [libjvm.so+0xd3d9d4] VM_GenCollectForAllocation::doit()+0x94
V [libjvm.so+0xd5a5e1] VM_Operation::evaluate()+0x91
V [libjvm.so+0xd57a52] VMThread::evaluate_operation(VM_Operation*)+0xc2
V [libjvm.so+0xd59159] VMThread::loop()+0x459
V [libjvm.so+0xd593a5] VMThread::run()+0xb5
V [libjvm.so+0xb0de64] java_start(Thread*)+0xf4
this reference is not in the originating generation
And for the "reference not active" case:
sun.misc.Cleaner @ 0x00000000f06b2b98 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xbbbb50] print_stack_trace_on(outputStream*)+0x20
V [libjvm.so+0xbbe6bb] ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V [libjvm.so+0x7c9b5c] instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V [libjvm.so+0xc2bbb5] ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V [libjvm.so+0x7438ad] OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V [libjvm.so+0x730dfb] GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V [libjvm.so+0x6467f4] DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V [libjvm.so+0x6493cb] DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V [libjvm.so+0x73002c] GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V [libjvm.so+0x57e567] GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V [libjvm.so+0xd3d9d4] VM_GenCollectForAllocation::doit()+0x94
V [libjvm.so+0xd5a5e1] VM_Operation::evaluate()+0x91
V [libjvm.so+0xd57a52] VMThread::evaluate_operation(VM_Operation*)+0xc2
V [libjvm.so+0xd59159] VMThread::loop()+0x459
V [libjvm.so+0xd593a5] VMThread::run()+0xb5
V [libjvm.so+0xb0de64] java_start(Thread*)+0xf4
this reference is not active
sun.misc.Cleaner @ 0x00000000f06ceb18 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xbbbb50] print_stack_trace_on(outputStream*)+0x20
V [libjvm.so+0xbbe6bb] ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V [libjvm.so+0x7c9b5c] instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V [libjvm.so+0xc2bbb5] ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V [libjvm.so+0x7438ad] OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V [libjvm.so+0x730dfb] GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V [libjvm.so+0x6467f4] DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V [libjvm.so+0x6493cb] DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V [libjvm.so+0x73002c] GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V [libjvm.so+0x57e567] GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V [libjvm.so+0xd3d9d4] VM_GenCollectForAllocation::doit()+0x94
V [libjvm.so+0xd5a5e1] VM_Operation::evaluate()+0x91
V [libjvm.so+0xd57a52] VMThread::evaluate_operation(VM_Operation*)+0xc2
V [libjvm.so+0xd59159] VMThread::loop()+0x459
V [libjvm.so+0xd593a5] VMThread::run()+0xb5
V [libjvm.so+0xb0de64] java_start(Thread*)+0xf4
this reference is not active
sun.misc.Cleaner @ 0x00000000f06ceb60 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xbbbb50] print_stack_trace_on(outputStream*)+0x20
V [libjvm.so+0xbbe6bb] ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V [libjvm.so+0x7c9b5c] instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V [libjvm.so+0xc2bbb5] ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V [libjvm.so+0x7438ad] OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V [libjvm.so+0x730dfb] GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V [libjvm.so+0x6467f4] DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V [libjvm.so+0x6493cb] DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V [libjvm.so+0x73002c] GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V [libjvm.so+0x57e567] GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V [libjvm.so+0xd3d9d4] VM_GenCollectForAllocation::doit()+0x94
V [libjvm.so+0xd5a5e1] VM_Operation::evaluate()+0x91
V [libjvm.so+0xd57a52] VMThread::evaluate_operation(VM_Operation*)+0xc2
V [libjvm.so+0xd59159] VMThread::loop()+0x459
V [libjvm.so+0xd593a5] VMThread::run()+0xb5
V [libjvm.so+0xb0de64] java_start(Thread*)+0xf4
this reference is not in the originating generation
...
Heap
def new generation total 4928K, used 4927K [0x00000000eae00000, 0x00000000eb350000, 0x00000000f0350000)
eden space 4416K, 100% used [0x00000000eae00000, 0x00000000eb250000, 0x00000000eb250000)
from space 512K, 99% used [0x00000000eb250000, 0x00000000eb2cfff8, 0x00000000eb2d0000)
to space 512K, 0% used [0x00000000eb2d0000, 0x00000000eb2d0000, 0x00000000eb350000)
tenured generation total 10944K, used 7772K [0x00000000f0350000, 0x00000000f0e00000, 0x00000000fae00000)
the space 10944K, 71% used [0x00000000f0350000, 0x00000000f0ae7258, 0x00000000f0ae7400, 0x00000000f0e00000)
compacting perm gen total 21248K, used 4842K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
the space 21248K, 22% used [0x00000000fae00000, 0x00000000fb2ba958, 0x00000000fb2baa00, 0x00000000fc2c0000)
No shared spaces configured.