jvm-判断对象是否存活
jvm空间不够就需要Garbage Collection了
一般共享区的都是要被回收比如堆区
以及方法区
。在进行内存回收之前要做的事情就是判断哪些对象是死的,哪些是活的。常用方法有两种引用计数法和可达性分析
引用计数法
思路是给java对象添加一个引用计数器,每当一个地方引用它时,计数器+1;引用失效则-1,当计数器不为0时,判断该对象存活;否则判断为死亡(计数器 = 0)
优点:实现简单,判断高效
缺点:无法解决对象间相互循环引用的问题
可达性分析
很多主流语言(如java、c#)都采用引用链法判断对象是否存活,大致的思路就是将一系列的 GC Roots对象作为起点,从这些起点开始向下搜索
在java语言中,可作为GC Roots的对象包含一下几种:
- 虚拟机栈中的引用的对象:在程序中正常创建一个对象,对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存到虚拟机栈中,如果对象生命周期结束了,那么引用就会从虚拟机栈中出栈,因此如果在虚拟机栈中有引用,就说明这个对象还是有用的,这种情况是最常见的
- 在类中定义了全局的静态对象:也就是使用了static关键字,由于虚拟机栈是线程私有的,所以这种对象的引用会保护在共有的方法区中,显然将方法区中的静态引用作为GC Roots是必须的
- 常量引用:就是使用了static final关键字,由于这种引用初始化之后不会修改,所以方法区常量池里的引用对象也应该作为GC Roots
- 使用JNI技术:有时候单纯的java代码并不能满足我们的需求,我们可能需要在java中调用c或c++的代码,因此会使用native方法,jvm内存中专门有一块本地方法栈,用来保存这些对象的引用,所以本地方法栈中引用的对象也会被作为GC Roots
GC Root主要步骤
-
可达性分析:当一个对象到GC Roots没有任何引用链相连时,则判断该对象不可达
注意:可达性分析仅仅是判断对象是否可达,但还不足以判断对象是否存活/死亡
-
第一次标记&筛选:筛选的条件对象如果没有重写finalize或者调用过finalize,则将该对象加入到F-Queue中
-
第二次标记&筛选:当对象经过了第一次的标记&筛选,会被进行第二次标记&准备被进行筛选。经过F-Queue筛选后如果对象还没有跟GC Root建立引用关系则被回收,属于给个二次机会