垃圾回收
1.如何判断对象为垃圾对象
1.1引用计数法
1.2可达性分析法
1.1引用计数法
在对象中添加一个引用计数器,当存在引用对象时,引用计数器的值+1,引用失效时,计数器-1
/**
* @PACKAGE_NAME: PACKAGE_NAME
* @Description:
* @Author: liangxu
* @Date: 2021/8/30 11:52 上午
* @Version: V1.0
*/
public class JVMTest {
private Object instance;
public static void main(String[] args) {
//1.对象进行两次引用
JVMTest t1 = new JVMTest();
JVMTest t2 = new JVMTest();
//对象间互相引用 此时达到的效果为t1引用计数器为2、t2引用计数器为2
t1.instance = t2;
t2.instance = t1;
//将对象设置为null后,引用计数器-1,t1引用计数器为1、t2引用计数器为1
t1 = null;
t2 = null;
//结论:
/**
* 如果JVM采用计数器进行内存释放的话,则存在不会被释放的垃圾对象占用内存,那么如何验证JVM是否使用了计数器进行内存管理呢,我们可以打印JVM观察。
*/
System.gc();
}
}
idea垃圾回收配置:
-Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails
-XX:+PrintGCDetails GC收集器
-XX:+UseSerialGC Serial收集器打印
-Xms20M -Xmx20M 堆内存
-Xmn10M 新生代内存
-XX:SurvivorRatio=8 Eden区域大小
如下图:
配置完成后,应用->运行。
从结果中我们可以看出:
我们当前的JVM对
1.2可达性分析算法
从GCRoot根节点向下检索,如不存在引用链,不能检索到的对象将被释放。
2.如何回收
1.1回收策略
1.1.1标记-清除算法
1.1.2复制算法
1.1.3标记-整理算法
1.1.4分代手机算法
1.2垃圾回收器
1.1.1Serial
1.1.2Parnew
1.1.3Cms
1.1.4G1
注:关于新声代老年代查看文档介绍
1.1 回收策略
1.1.1标记-清除算法(老年代)
效率问题
空间问题
上图我们可以看出,红色代表使用的,黄色代表标记的,白色代表未使用的。当黄色被清除后,堆内存变成一块一块,占用率降低。并且当它再不停检索时,因为块不断增加,导致效率低下
缺点:两次扫描,严重浪费时间,
1.1.2复制算法(新生代)
1.堆
1.1新声代
Eden 伊甸园
Survivor 存活区
Tenured Gen
1.2老生代
2.方法区
3.栈 本地方法栈 程序计数器
提高内存利用率,将内存分为3大块。
Eden用来存储内存初始化对象。在回收时,将在使用的的内存,存放到Survivor,如果在使用大于在使用的内存,则会借用Tenured Gen“内存担保”存储。
好处:没有内存的碎片
坏处:浪费内存空间:多了一半空间永远是空的to。假设对象100%存活(极端情况)
复制算法最佳使用场景:对象存活度较低的时候:新生代
1.1.3标记-整理算法(老年代)
使用和未使用的移动到两端,最后清除未使用的。高效。
总结:
内存效率:复制算法->标记清除算法->标记压缩算法(时间复杂度)
内存整齐度:复制算法=标记压缩算法->标记清除算法
内存利用率:标记压缩算法=标记清除算法->复制算法
难道没有最优的算法吗?
答案:没有最好的算法,只有最合适的算法
GC分代收集算法
年轻代:
存活率低,采用复制算法
老年代:
区域大,存活率高,采用标记清除(内存碎片不是太多)+标记压缩混合实现
1.1.4分代收集算法
分代收集算法即针对新生代采用复制算法,针对老年代采用标记整理算法。
1.2 垃圾回收器
1.1.1Serial收集器(客户端收集)
最基本,发展最悠久
单线程垃圾收集器
1.1.2Parnew
多线程收集
效率相比Serial要高,但如果在客户端的话,建议使用Serial
1.1.3Parallel Scavenge 收集器(服务器收集器)
复制算法(新生代收集器)
多线程收集器
达到可控制的吞吐量(吞吐量:CPU用于运行用户代码的时间与CPU消耗的总时间的比值 吞吐量=(执行用户代码时间)/(执行用户代码的时间+垃圾回收所占用的时间))
-XX:MaxGFPauseMillis 垃圾收集器最大停顿时间
-XX:CGTimeRatio 吞吐量大小
1.1.3Cms收集器(Concurrent Mark Sweep 并发标记清除)
并发收集器,用于回收老年代内存。
1.工作过程
初始标记
并发标记(边扔垃圾边打扫)
重新标记
并发清理
优点
并发收集
低停顿
缺点
占用大量的CPU资源
无法处理浮动垃圾
出现Concurrent Mode Failure (并发清理时,会出现问题)
空间碎片
初始标记:可被回收的对象。(可达性分析法)
并发标记
重新标记:因程序继续运行而导致的变动的对象进行重新标记
并发清理
1.1.4 G1收集器
注:重量级
优势:
1.并行与并发
2.分代收集
3.空间整合(标记整理清除)
4.可预测的停顿
步骤:
1.初始标记
2.并发标记
3.最终标记
4.筛选回收
如上图:在对象写入时,通过可达性分析发判断,如果对象的引用在不同的内存块中,则记录入remeber set表中。从而达到不需要垃圾回收筛选时,不需要扫描所有的内存块。提高效率。
3.何时回收
引用计数法
在对象中添加一个引用计数器,当存在引用对象时,引用计数器的值+1,引用失效时,计数器-1