二、垃圾收集器与内存分配策略
一、Java采用可达性算法
虚拟机采用可达性分析来判断对象是否存活的。
它们已GC root对象为起点,向下搜索所有和GC root对象直接或间接关联对象。所走过的路径为引用链。当一个对象没有到GC root的路径时认为该对象不可用。
在图中obj4和obj5将被认为是可回收对象,因为没有关联到GC ROOT的路径
image.png
二、可以作为GC ROOT的对象
1.虚拟机栈中局部变量引用对象
2.类的静态属性引用对象
3.常亮引用对象
4.native方法引用对象
三、强引用关系
1.强引用:只要有引用关系,那么就不被回收
2.软引用:当系统内存不足时被回收
3.弱引用:只要GC就回收
4.虚引用:能够在垃圾回收时收到一个系统发出的通知,和弱引用强度一致
四、虚拟机垃圾回收的机制
1.首先会进行一次筛选标记,如果对象不可达,将进行筛选
2.筛选条件是有没有必要调用finalize()方法,当对象没有重写该方法,或者finalize方法已经被调用过,那么将不被执行。如果认为可以调用,那么将加入到F-QUEUE队列中
3.所有在队列中的对象都被执行第二轮标记,开启一个线程调用队列中的finalize方法,如果这时候有对象的finalize方法中让该对象和任何对象关联,都将被移除队列
finalize方法的优先级很低
public static A a=null;
publc class A{
protected void finalize() throws Throwable{
a=this;
}
}
main{
a=new A();
a=null;
// gc会调用finalize方法,让对象自身进行一次拯救。这里A的方法又重新关联了一个引用。
System.gc();
Thread.sleep(500);
}
四、类的回收
符合以下三点的类可以被回收:
1.当堆中不存在任何该类的实例
2.加载该类的ClassLoader被回收
3.Class没有被任何地方反射到
//控制类的回收
-Xnoclassage:
五、垃圾收回算法
1.标记清楚法
标记出要清理的,然后进行清理。会产生大量的不连续的内存
2.复制清除法
分配一个Edrn区和两个大小相等的survivor空间。每次清理Edrn和一块survivor区,把剩下的复制到另一块。Edrn和survivor区的空间是8:1:1的关系。
3.标记整理法
同样采用标记清理,但是在标记后将所有不清理的对象移动到内存的一边,清理另一边的内存。
OopMap协助GC
虚拟机中有一个OopMap的数据结构来负责,当类加载的完成后,虚拟机就把对象内的引用关系记录下来
GC的时间点
虚拟机有safePoint机制,当程序执行到“安全点时”(方法调用,异常跳转等就会产生安全点)。虚拟机采用主动中断的机制。当GC需要中断线程时会设置一个标志位,每个线程都去读哪个标志位,当为true时,就主动中断。