性能文章>PhantomReference? 虚引用? OOM?>

PhantomReference? 虚引用? OOM?原创

9445612

背景

关于各种引用参考
https://www.geeksforgeeks.org/types-references-java/
在我之前认知中,虚引用除了自身对象占用内存外,其引用对象referent在不可达时应该是已经被回收,使用示例验证一下
image.png
image.png
实际却不是这样,上面两个样例都是用参数-Xmx50m运行发现使用PhantomReference时会导致OOM,而使用SoftReference是正常运行的。
在确认PhantomReference与SoftReference都没有添加多余字段,也就证明这两个对象除去referent占用内存应该是一致的。

复现

按之前想法,经历一轮gc后PhantomReference所引用的referent对象应该为空[这里不能get()来获取,因为此方法一直会返回null],示例断点验证一下
image.png
image.png
从两个不同示例来看,PhantomReference所引用的referent对象经过一次gc后并不为null,但是在ReferenceQueue队列中存在此对象也就证明ModelSon对象是可回收的。

分析

PhantomReference源码中有一段注释
image.png
说明了PhantomReference和软引用、弱引用不一样的是PhantomReference加入队列后并不会自动被gc清理,也就是需要手动清理。
在gc时都会调用ReferenceProcessor::process_discovered_references方法处理各种引用
image.png
从process_discovered_references实现中可以看到在调用方法process_discovered_reflist软引用和虚引用第三个参数是不一样的,process_discovered_reflist继续往下可以看到第三个参数是clear_referent,这个参数只在process_phase3[并行处理实现是一样的]中有使用此参数,继续往下
image.png
可以看到当clear_referent为false时会将referent对象标记成存活,虽然会进入ReferenceQueue队列,但是referent对象其实还是在内存中的,这就解释了之前使用PhantomReference会导致OOM的问题。

使用

那么PhantomReference到底是怎么用的呢?
有一种用法是代替finalize方法的实现,PhantomReference可以作为一种代替方案。
image.png
image.png

总结

PhantomReference在jvm中只是不影响gc处理,并不代表其不会强引用referent,所以还是需要自己调用clear方法清理对referent对象的强引用。

问题

这里只是对于PhantomReference导致OOM的问题追查,实际上还有很多细节需要了解,列出其中两点

  1. SoftReference为什么修改clock就可以回收软引用[可以查看should_clear_reference的实现和调用方]
  2. 与java.lang.ref.FinalReference的区别是什么

1.关于SoftReference在内存使用很少的情况使其对象回收,可以通过修改SoftReference字段clock为一个比较大的值,在gc的时候触发SoftReference回收
2.关于对象是否被回收验证可以使用hsdb,也可以下载jar执行attach后,使用objectvisit命令查找对象是否存在
https://github.com/RookieZQF/enhance-hsdb/blob/master/lib/clhsdb-enhance-2021-03-jar-with-dependencies.jar
wget https://raw.githubusercontent.com/RookieZQF/enhance-hsdb/master/lib/clhsdb-enhance-2021-03-jar-with-dependencies.jar
image.png

点赞收藏
Rookie_267692
请先登录,查看6条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

12
6