GC算法(垃圾标记阶段)
概述
该阶段判断存活对象有引用计数算法和可达性分析算法
引用计数算法
优点
较高的实时性:计数器为0就可以触发GC回收,无需等待内存情况再GC。
局部性:每个对象都包含各自的计数器,因此GC只针对具体的对象进行不会涉及到整体
缺点
浪费cpu性能
当每次对象被引用或者引用失效时,计数器都会进行计算。但是对于循环引用引用计数器无法进行解决。一个闭环的循环引用,由于计数器都不为0 ,因此并不会被GC,造成内存溢出也是并不奇怪的。
class one {public three useThree;}class two {public one useOne;}class three {public two useTwo;}public class ObjectSurvival {public static void main(String[] args) {three useThree = new one().useThree;one useOne = new two().useOne;two useTwo = new three().useTwo;}}
目前在Java中已经被废弃了。
GCROOTS
public class Common {private String value;}
什么类型的对象可以作为GCROOTS
虚拟机栈(栈帧中的本地变量表)中引用的对象
public class GCROOTS {public static void main(String[] args) {Common common = new Common();common = null;}}
“common“是栈帧中的本地变量,是GCROOTS。当”common“ = null,”common“ 断开了与new Common()的联系,因此会被GC回收。
方法区中类静态属性引用的对象
public class GCROOTS_static {private static Common common;public static void main(String[] args) {GCROOTS_static gcroots_static = new GCROOTS_static();gcroots_static.common = new Common();gcroots_static = null;}}
“gcroots_static ”是栈帧中的本地变量,是GCROOTS,”common“是对其他实例对象的静态引用。new Common() 给变量”common“赋值了引用且”common“为静态引用,因此是一个GCROOTS。当”gcroots_static” = null断开了与new GCROOTS_static()的联系因此会被回收,而“common”不会被回收。
方法区中常量引用的对象
public class GCROOTS_const {private static final Common common = new Common(); //常量引用对象public static void main(String[] args) {Common common1 = new Common(); //新实例对象,对照对象common1 = null;}}
对于常量引用的对象属于静态不会跟随其他引用的回收而回收。
本地方法栈中JNI中引用的对象
一般说的本地native方法
可达性分析算法
在使用可达性算法的过程中,内存中的存活对象都会被跟对象集合(GC Root Set)直接或者间接链接着,所走过的路径为引用链。
没有被GCROOTS引用链直接或者间接链接的对象可以被标记为可回收对象。
