JVM在垃圾回收时如何判断对象是否存活

JVM有两种算法来判断对象是否存活,分别是引用计数法可达性分析算法

引用计数法

        给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。

        假设A对象引用了B对象,B对象引用了A对象,那么A和B对象的计数器就永远都是大于0。当A对象或者B对象不再使用时,使用该算法判断,A对象或B对象永远都是存活的,这就导致了A对象和B对象不能被正确回收,造成内存泄露。

可达性分析算法

        这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

        但是,并不是说当进行完可达性分析算法后,即可证明某对象可以被GC。对象是否存活,需要两次标记:

  • 第一次标记:垃圾收集器首次发现一个对象是不可达的并且该对象覆盖了 finalize 方法时,会将这个对象放入一个名为 finalization queue 的队列中,而不是立即回收该对象。
  • Java 虚拟机(JVM)中有一个专门的线程(Finalizer 线程)从 finalization queue 中取出对象并调用它们的 finalize 方法。这个过程是异步的,且不保证 finalize 方法会立即执行。
  • 重新标记:在 finalize 方法执行期间,如果该对象重新变得可达(例如,通过在 finalize 方法中将其自身赋值给某个静态变量),则该对象将从 finalization queue 中移除,并不会被回收。
  • 回收:如果在 finalize 方法执行完毕后,该对象仍然不可达,则它将被垃圾收集器在下一次 GC 过程中回收。

        不过现在都不提倡覆盖finalize方法,它的本意是像Cpp一样在对象销毁前执行,但是它影响了JAVA的安全和GC的性能,所以第二种判断会越来越少。

哪些内容可以作为可达性分析算法的GC Roots

        GC Roots是作为可达性分析算法的起点的。要实现语义正确的可达性分析,就必须要能完整枚举出所有的GC Roots,否则就可能会漏扫描应该存活的对象,导致GC错误回收了这些被漏扫的活对象。那么,所谓“GC Roots”,就是一组必须活跃的引用。

  • Thread 当前活着的线程
  • 方法中的局部变量
  • JNI Local - JNI方法的local变量或参数
  • JNI Global - 全局JNI引用
  • 被同步锁(synchronized)持有的对象
  • 跨代引用的问题,会把Remembered Set也作为GC Root。

可达性分析算法的缺陷

  • STW(Stop The World)的时间长                                                                                                                                 可达性分析算法需要对程序进行全局分析,因此时间复杂度较高,可能需要很长的时间才能  完成分析,并且整个过程都是STW的,所以对应用的整体性能有很大影响。这也使得可达性分析算法难以适用于大型程序的分析。解决这个问题的主要方法是三色标记法。
  • 内存消耗                                                                                                                                          可达性分析算法需要存储程序中所有的对象和它们之间的引用关系,这些信息需要占用大量的内存空间。对于大型程序,如果要进行完整的可达性分析,需要存储的对象数量和引用关系数量都非常大,可能会导致内存空间不足或者程序性能下降的问题。

               

                

                                                                                                                              

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值