jvm-判断对象是否存活

Author Avatar
丁起男 12月 29,2020
  • 在其它设备中阅读本文章

jvm-判断对象是否存活

jvm空间不够就需要Garbage Collection了

一般共享区的都是要被回收比如堆区以及方法区。在进行内存回收之前要做的事情就是判断哪些对象是死的,哪些是活的。常用方法有两种引用计数法可达性分析

引用计数法

思路是给java对象添加一个引用计数器,每当一个地方引用它时,计数器+1;引用失效则-1,当计数器不为0时,判断该对象存活;否则判断为死亡(计数器 = 0)

优点:实现简单,判断高效

缺点:无法解决对象间相互循环引用的问题

可达性分析

很多主流语言(如java、c#)都采用引用链法判断对象是否存活,大致的思路就是将一系列的 GC Roots对象作为起点,从这些起点开始向下搜索

在java语言中,可作为GC Roots的对象包含一下几种:

  1. 虚拟机栈中的引用的对象:在程序中正常创建一个对象,对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存到虚拟机栈中,如果对象生命周期结束了,那么引用就会从虚拟机栈中出栈,因此如果在虚拟机栈中有引用,就说明这个对象还是有用的,这种情况是最常见的
  2. 在类中定义了全局的静态对象:也就是使用了static关键字,由于虚拟机栈是线程私有的,所以这种对象的引用会保护在共有的方法区中,显然将方法区中的静态引用作为GC Roots是必须的
  3. 常量引用:就是使用了static final关键字,由于这种引用初始化之后不会修改,所以方法区常量池里的引用对象也应该作为GC Roots
  4. 使用JNI技术:有时候单纯的java代码并不能满足我们的需求,我们可能需要在java中调用c或c++的代码,因此会使用native方法,jvm内存中专门有一块本地方法栈,用来保存这些对象的引用,所以本地方法栈中引用的对象也会被作为GC Roots

GC Root主要步骤

  • 可达性分析:当一个对象到GC Roots没有任何引用链相连时,则判断该对象不可达

    注意:可达性分析仅仅是判断对象是否可达,但还不足以判断对象是否存活/死亡

  • 第一次标记&筛选:筛选的条件对象如果没有重写finalize或者调用过finalize,则将该对象加入到F-Queue中

  • 第二次标记&筛选:当对象经过了第一次的标记&筛选,会被进行第二次标记&准备被进行筛选。经过F-Queue筛选后如果对象还没有跟GC Root建立引用关系则被回收,属于给个二次机会

原文:https://mp.weixin.qq.com/s/GfAfffbF_uiphN0Zd3YouQ