Java: 链表head取出用后,置next=null为何可以加速gc?
下面是LinkedList中的unlinkFirst方法源码
其中f是链表的head
里面说f.next = null; 是有利于gc
我不太理解,f此时已经ROOT不可达
必定要gc的
将其next置为null为何有助于gc?
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
参考一篇文章: https://www.javaspecialists.e...
如有openjdk源码,则可用如下命令查找添加// help GC的时间和rev号
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确实没有问题,但是楼主从另一个角度试想一下。
如果我从头部删除一个元素之后。又删除了一次头部元素呢??
那么将形成:
f2是被f1引用的,f1未被引用 (不考虑外部持有的情况下)
在调用完unlink之后,当前调用的线程或者方法并未达到能够触发GC停顿的Safepoint。那么刚刚删除掉的f并没有立刻回收。
此时创建新对象的时候:
问题就在这里了。综上所述,如未设置f.next = null。在未触发Safepoint的情况下连续删除两次头部元素。f1和f2之间将存在引用关系。
如有新对象需要创建且新生代内存不足时。f2将被提升至老生代而不是立刻被回收。
补充:
专三党,如有纰漏望各位前辈指正
f 并不一定不可达
比如ListItr就有可能持有 f 的引用
如果没有这行
有可能当LinkedList不再使用需要GC时,因为有别的对象持有 ListItr,ListItr 又持有 f,
而 f.next 又指向其他节点,导致 LinkedList 里面的节点不会被GC,内存泄漏。
这是我的理解,有不对的请指正。
用代码补充一下