下面接着上一篇介绍第2阶段和第3阶段的处理逻辑。
第2个阶段移除所有的referent还存活的Reference,也就是从refs_list中移除Reference。process_phase2()方法的实现如下:
// Phase2: remove all those references whose referents are reachable. inline void process_phase2(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { // complete_gc is ignored in this case for this phase pp2_work(refs_list, is_alive, keep_alive); // ... }
在第2阶段移除所有的对象可达的Reference,因为不需要进行垃圾回收。
// Traverse the list and remove any Refs that are not active, or // whose referents are either alive or NULL. void ReferenceProcessor::pp2_work( DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive ) { DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(); if (iter.is_referent_alive()) { // The referent is reachable after all. // Remove Reference object from list. iter.remove(); // Update the referent pointer as necessary: Note that this // should not entail any recursive marking because the // referent must already have been traversed. iter.make_referent_alive(); iter.move_to_next(); } else { iter.next(); } } }
调用iter.is_referent_alive()方法判断,如果referent还存活,那么从refs_list中删除对应的Reference对象即可。这个操作对于所有的引用类型(软引用、弱引用、幻像引用和最终引用)都一样。
第3阶段在处理referent时,这个referent可以确保是存活状态,不过还需要做一些其它操作。process_phase3()方法的实现如下:
// Traverse the list and process the referents, by either // clearing them or keeping them (and their reachable // closure) alive. void ReferenceProcessor::process_phase3( DiscoveredList& refs_list, bool clear_referent, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc ) { ResourceMark rm; DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.update_discovered(); iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); if (clear_referent) { // NULL out referent pointer // 将Reference的referent字段置为null,之后会被GC回收 iter.clear_referent(); } else { // keep the referent around // 标记引用的对象为存活,该对象在这次GC将不会被回收 iter.make_referent_alive(); } iter.next(); } // Remember to update the next pointer of the last ref. iter.update_discovered(); // Close the reachable set complete_gc->do_void(); }
对于软引用和弱引用来说,参数clear_referent的值为true,也就是当对象不可达后,引用字段就会被置为null,然后对象就会被回收(对于软引用来说,如果内存足够的话,在Phase 1,相关的引用就会从_refs_list中移除);对于最终引用和幻像引用来说, 参数clear_referent的值为false,也就意味着被这两种引用类型引用的对象,如果没有其他额外处理,只要Reference对象还存活,那引用的对象是不会被回收的。
参考文章:
(1)你不可不知的Java引用类型之——SoftReference源码详解
原文:https://www.cnblogs.com/mazhimazhi/p/13503996.html