如有openjdk源码,则可用如下命令查找添加// help GC的时间和rev号
hg annotate -ufd src\java.base\share\classes\java\util\LinkedList.java
rev 66ef929d58f2 2009-11-06
可以参考《深入理解Java虚拟机》,楼主应该是有这本书的。试想一个问题,gc会检测GC Roots。切记,是Roots!
GC Roots是由多个Root组成的。现代JVM使用的是准确性GC。达到能够触发GC停顿的Safepoint时,并不会检查所有上下文和全局引用的Root。而是通过OopMap数据结构计算出对象偏移量和类型。在OopMap的辅助下,HotSpot可以快速地检查GC Roots。
按照常规逻辑来说,不设置f.next = null确实没有问题,但是楼主从另一个角度试想一下。
如果我从头部删除一个元素之后。又删除了一次头部元素呢??
那么将形成:
f1.next = f2
f2.next = head
f2是被f1引用的,f1未被引用 (不考虑外部持有的情况下)
在调用完unlink之后,当前调用的线程或者方法并未达到能够触发GC停顿的Safepoint。那么刚刚删除掉的f并没有立刻回收。
此时创建新对象的时候:
如果内存不够且新生代中能够释放足够的空间,则新对象直接放入。
如果内存不够存放新对象,新生代对象会被提升至老生代。腾出空间将放入新对象
问题就在这里了。综上所述,如未设置f.next = null。在未触发Safepoint的情况下连续删除两次头部元素。f1和f2之间将存在引用关系。
如有新对象需要创建且新生代内存不足时。f2将被提升至老生代而不是立刻被回收。
补充:
不设置为null并不会导致内存泄露问题。
对GC优化极其细微,应当考虑目前的GC实现。引用原文中使用的JDK1.4,原始代码在JDK12且内存足够的情况下无明显差别
专三党,如有纰漏望各位前辈指正