jvm培训:判断对象是否存活的算法

    1、引用计数法     引用计数方法的实践是为每个对象添加一个引用计数器,以对指向该对象的引用数进行计数。当有对对象的引用时,计数器增加1,当引用无效时,计数器减少1,并且对象计...

attachments-2020-12-Jk32RVAq5fdb00d49ef46.jpg

    1、引用计数法


    引用计数方法的实践是为每个对象添加一个引用计数器,以对指向该对象的引用数进行计数。当有对对象的引用时,计数器增加1,当引用无效时,计数器减少1,并且对象计数器是否为0以确定对象是否可以回收。一旦对象的引用计数器为0,则意味着该对象已死并且可以回收。


    (1)具体实现如果有一个引用,被赋值为某一对象,那么该对象的引用计数器+1。如果一个指向某一对象的引用,被赋值为其他值,那么将该对象的引用计数器-1。也就是说,我们需要截获所有的引用更新操作,并且相应的增减目标对象的引用计数器。


    (2)缺点除了需要额外的空间来存储计数器,以及繁琐的更新操作,引用计数法还有一个重大的漏洞——无法处理循环引用对象。


    举个例子,假设对象a与b相互引用,除此之外没有其他引用指向a或者b。在这种情况下,a和b实际上已经死了,但由于它们的引用计数器皆不为0,所以这些循环引用对象所占据的空间将不可回收,从而造成了内存泄露。

jvm培训


    2、可达性分析


    目前,Java虚拟机的主流垃圾收集器采用可达性分析算法。可达性分析算法的本质是使用一系列GC根作为初始活动集,然后从该集开始,探索该集可以引用的所有对象,然后将它们添加到该集。此过程也称为Mark。最后,未开发的对象已死,可以恢复。


  jvm培训

  

    可达性分析可以解决引用计数法不能解决的循环引用问题。还拿上面例子说明,即便对象a和b相互引用,只要从GCRoots出发无法到达a或者b,那么可达性分析便不会将它们加入存活对象合集中。


    GCRoots暂时理解为由堆外指向堆内的引用,一般来说,GCRoots包括以下几种:


    Java方法栈帧中的局部变量


    已加载类的静态变量


    JNIhandles


    已启动且未停止的Java线程


    缺点


    在多线程环境下,其他线程可能会更新已经访问过的对象中的引用,从而造成误报(将引用设置为null),或者漏报(将引用设置为未被访问过的对象)。


    如果发生了误报,Java虚拟机最多损失了部分垃圾回收的机会。漏报比较麻烦,因为垃圾回收器可能回收事实上仍被引用的对象内存。一旦从原引用访问已经被回收了的对象,则很有可能会直接导致Java虚拟机崩溃。


推荐阅读:jvm培训:如何判断哪些对象需要回收?


  • 发表于 2020-12-17 14:55
  • 阅读 ( 246 )
  • 分类:技术干货

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
JAVA Q&A
JAVA Q&A

173 篇文章

作家榜 »

  1. JAVA Q&A 173 文章
  2. 江南 1 文章
  3. 伯乐 0 文章
  4. 孤存 0 文章
  5. q21164340 0 文章
  6. 赫敏12 0 文章
  7. 子牙 0 文章
  8. 赫敏 0 文章