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引用链直接或者间接链接的对象可以被标记为可回收对象。