JVM-垃圾回收

1 概念

  1. System.gc() = Runtime.getRuntime().gc() 会显示触发Full GC ,提醒jvm的垃圾回收器执行gc,无法保证对垃圾收集器的立刻调用
    System.runFinalization() 强制调用使用引用的对象的finalize()方法

  2. 内存溢出:OOM ,没有空闲内存,并且垃圾收集器也无法提供更多内存 (1堆内存小 2大量对象)

  3. 内存泄漏:对象不会再被程序用到,但GC又不能回收(宽泛意义:生命周期无效的延长,如局部变量变成成员变量)
    例:单例模式生命周期长;socket、数据库连接等资源关闭; 不能算循环引用

  4. STW :stop the world

  5. 引用:有引用的情况下 ->
    强引用:直接引用赋值obj = new Object(),即使OOM也不回收,只有没有引用的时候才会回收
    软引用:将要发生内存溢出之前,会将该对象列入回收范围,二次回收(高速缓存)
    弱引用:只有垃圾收集,就直接回收; WeakHashMap extends WeakReference
    虚引用:对象回收跟踪(构造器必须传入一个引用队列)

  6. 垃圾:运行程序中没有任何指针指向的对象

  7. finalization机制:垃圾回收之前,总会先调用finalize(),protected修饰,可重写:用于资源释放,关闭流、链接等。

    永远不要手动调用finalize(),应交给垃圾回收机制:①、可能复活对象; ②、不会马上调用,由GC线程控制; ③、方法体差影响性能
    (可回收至少被标记两次)

    由于finalize()的存在,所以jvm的对象可能存在三种状态:
    在这里插入图片描述在这里插入图片描述

  8. java:自动内存分配、自动垃圾收集

2 回收算法

2.1 标记阶段:(对象是否 存活 -> 没有指针引用)

2.1.1 引用计数算法 : python

原理:有一个对象引用时计数器+1,引用失效就-1。=0时可回收

优:实现简单,便于识别;判定效率高,回收没有延迟
缺:空间-计数器;时间-加减法;(致命)无法处理循环引用

在这里插入图片描述
– java没使用引用计数;

– python有使用:①手动解除循环引用;②使用弱引用weakref

2.1.2 可达性分析算法 :java 和 C# 默认

也叫:根搜索算法 或 追踪性垃圾收集

在这里插入图片描述
原理:GC Roots 根节点作为起点,向下搜索引用的对象,找到的标记为非垃圾,其余为垃圾

根节点
在这里插入图片描述

2.2 清除阶段

清除:并未真的置空,而是存了需要清除对象的地址,下次有对象加载时,如果空间足够,直接覆盖

2.2.1 标记-清除算法 :(Mark-Sweep)

过程:-> 内存耗尽之后 -> STW
-> 标记:Collector从引用根节点开始遍历,标记所有被引用的对象。标记可达对象(标记非垃圾) -> 记录在对象Header
-> 清除:堆内存从头到尾线性遍历,Header中没有标记,则回收
在这里插入图片描述
优:基础常见
缺:效率不高(遍历)、GC时STW、不连续产生内存碎片,需要空闲列表

2.2.2 复制算法 :(新生代survivor区)

从根节点开始,可达对象都复制到新的区域
在这里插入图片描述
优:没有标记清除过程,运行高效; 没有碎片
缺:需要2倍内存;G1中大量region的GC,内存占用和时间开销较大

2.2.3 标记-压缩算法 :(Mark-Compact 老年代)

在这里插入图片描述
优:没有碎片; 不用2倍内存
缺:效率比清除低;STW

2.2.4 分代收集算法 : 几乎所有的GC都是用分代收集

年轻代:朝生夕死 复制算法
老年代:标记清除 标记整理混合实现 -> CMS基于标清实现回收,标整碎片整理

2.2.5 增量收集算法、分区算法

3 垃圾回收器

垃圾回收器指标:吞吐量(用户代码时间/用户代码+垃圾收集)、(*)暂停时间、内存占用、垃圾收集开销、收集频率、快速

!在最大的吞吐量优先情况下,降低停顿时间。可控的停顿时间范围内,最大程度的增大吞吐量。

在这里插入图片描述
在这里插入图片描述
串行:Serial (单核,复制算法,串行回收 新)、Serial Old (单核,标记-压缩算法,串行回收 老) -> 简单高效
并行(STW):ParNew(并发 新生代)、 (java8默认)Parallel Scavenge(吞吐量 新)、(java8默认)Parallel Old 老
并发:CMS(低延迟 标记-清除 老)、(java9默认)G1
CMS:
初始标记:标记GC Roots能直接关联的对象 (短STW)
并发标记:并发的从GC Roots遍历整个对象图(并发没有STW)
重新标记:修正并发标记期间,变动部分 (短STW)
并发清除:并发的清理删除标记阶段的垃圾对象(没有整理碎片)
为什么不用标记压缩算法:因为并发的清理,保证用户线程使用,所以没法整理碎片
缺:产生内存碎片、占用CPU资源、无法处理浮动垃圾(并发标记时由正常变为垃圾)
G1:区域分代化 多核CPU和大容量内存的机器
将堆空间分为若干个区域region,region之间复制算法,整体上看是标记压缩,都能避免碎片化。
可预测的停顿时间模型:region价格排序
卡表、Remembered Set
缺:内存占用
G1替换CMS:
1.超过50%的java堆被活动数据占用
2.对象分配频率或者年代提升频率变化很大
3.GC停顿时间过长(>0.5~1)

3.1 Serial回收器:串行回收

在这里插入图片描述

3.2 ParNew回收器:并行回收

在这里插入图片描述

3.3 Parallel Scavenge回收器:吞吐量优先 (jdk1.8默认)

自适应调节策略,根据配置的吞吐量等,调节8:1:1的比例

在这里插入图片描述

3.4 CMS回收器:低延迟

在这里插入图片描述
在这里插入图片描述

小结:
最小化内存和并行开销:Serial
最大化吞吐量:Parallel
最小化停顿时间:CMS

3.5 G1回收器:分区算法,区域分代化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6 Serial回收器

3.7 Serial回收器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值