垃圾回收知识点总结

垃圾回收知识点总结

垃圾回收(Garbage Collect)

1、如何确定一个对象是一个垃圾
1.1:引用计数法
对于某个对象而言,只要是应用程序中持有该对象的引用,就说明该对象不是垃圾,如果没有任何指针对其引用,那么他就是垃圾
弊端:
如果AB相互持有引用,则会导致该对象永远不会被回收.
1.2:可达性分析
通过GC Root的对象,开始向下寻找,看某个对象是否可达
在这里插入图片描述
而能作为GC Root的有:
类加载器
Thread
虚拟机栈的本地变量表
static成员
常量引用
本地方法栈的变量

2、什么时候会垃圾回收
GC是由JVM自动完成的,根据系统环境而定,所以时机是不确定的,但是,我们可以手动的进行垃圾回收,如:调用System.gc()方法进行一次垃圾回收,但是具体什么时刻运行也无法将其控制,即就是System.gc()只是通知垃圾回收器进行垃圾回收,但是什么时刻回收是由JVM决定的.但是不建议手动调用该方法,因为GC消耗的资源比较大.
2.1:什么时候会触发垃圾回收
1、当Eden区或者是S区不够用的时候
2、老年代空间不够用了
3、方法区空间不够用的时候
4、System.gc()

3、垃圾回收算法
当一个对象确定为师垃圾对象时,这时如何回收该对象呢?就得有对应的垃圾回收算法,下面是常见的几种垃圾回收算法
3.1:标记——清除(Mark-Sweep)
标记:找出内存中需要回收的对象,将其标记出来(此时堆中的所有对象都将会被扫描一遍,从而才能确定需要回收的对象,所以此举比较耗时)
在这里插入图片描述
清除:清除掉被标记的需要回收的对象,释放出对应的内存空间
在这里插入图片描述
该方法的缺点:
标记清除之后会产生大量不连续的空间碎片,空间碎片太多可能会导致以后在程序运行期间产生的需要分配较大对象时,无法找到足够的连续内存二不得不提前触发另一次垃圾收集动作。
1、标记清除两个过程都比较耗时,效率不高
2、会产生大量不连续的空间碎片,空间碎片太多可能会导致以后程序在运行过程中需要分配较大对象时,无法找到足够的内存而不得不提前触发另一次垃圾收集动作.
3.2、标记——复制(Mark-Copying)
将内存划分为两块相等的区域,每次只使用其中一块,如下:
在这里插入图片描述
当其中一块内存使用完了,就将还存活的对象复制到另外一块上面,然后把已经使用过的内存空间一次清除掉
在这里插入图片描述
缺点:空间利用率降低
3.3、标记——整理(Mark-Compact)
复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低,更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都有100%存活的极端情况,所以老年代一般不能直接选用这种算法。
标记过程仍然与“标记——清除”算法一样,但是后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
其实上述过程相对于“复制算法”来讲,少了一个“保留区”。
在这里插入图片描述
让所有存活的对象都向一端移动,清理掉边界以外的内存
在这里插入图片描述
3.4、分代收集算法
上面介绍理三种垃圾收集算法,那么在堆内存中使用的是哪一个呢?
Young区:复制算法(对象在分配之后,可能生命周期比较短,Young区复制法效率比较高)
Old区:标记清除或标记整理(Old区对象存活时间比较长,复制来复制去反而没必要,所以先标记再清理比较好)
4、垃圾收集器
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体体现
在这里插入图片描述
4.1:Serial
Serial收集器是最基本发展历史最悠久的收集器,曾经(在JDK 1.3.1之前)是虚拟机新生代收集的唯一选择,他是一种单线程收集器,不仅仅意味着他只会使用一个CPU或者一条收集线程去完成垃圾收集工作更重要的是其在运行垃圾收集的时候需要暂停其他线程.
优点:简单高效,拥有很高的单线程收集效率
缺点:收集过程中需要暂停所有线程
算法:复制算法
适用范围:新生代
应用:Client模式显得默认新生代收集器
在这里插入图片描述
4.2:Serial Old
Serial Old收集器是Serial收集器的老年代版本,也是一个单线程收集器,不同的是采用"标记——整理算法"运行过程和Serial收集器一样
在这里插入图片描述
4.3:ParNew
可以将ParNew收集器理解为Serial收集器的多线程版本
优点:在多CPU时,比Serial效率高
缺点:收集过程暂停所有应用程序的线程,但CPU时比Serial效率高
算法:复制算法
适用范围:新生代
应用:运行在Server模式下的虚拟机中首选的新生代收集器
在这里插入图片描述
4.4:Parallel Scavenge
Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,看上去和ParNew一样,但是Parallel Scavenge更关注的是系统的吞吐量
吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾收集的时间)
吞吐量越大,意味着垃圾收集的时间越短,则用户大妈可以充分利用CPU资源,尽快完成程序的运算任务-XX:MaxGCPauseMillis控制最大的垃圾收集停顿时间, -XX:GCRatio直接设置吞吐量的大小。
4.5:Parallel Old
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程和标记——整理算法进行垃圾回收,也是更加关注系统的吞吐量
4.6:CMS
添加链接描述
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器
采用的是“标记——清除算法”整个过程分为4步
(1)初始标记 CMS initial mark 标记GC Roots直接关联对象,不用Tracing,速度很快
(2)并发标记 CMS concurrent mark 进行GC Roots Tracing
(3)重新标记 CMS remark 修改并发标记因用户程序变动的内容
(4)并发清除 CMS concurrent sweep 清除不可达对象回收空间,同时有新垃圾产生,
留着下次清理称为 浮动垃圾
由于整个过程中,并发标记和并发清除,收集器线程可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发地执行的。
在这里插入图片描述
优点:并发收集,低停顿
缺点:产生大量的控件碎片,并发阶段会降低吞吐量
4.7:G1(Garbage-First)
官网
使用G1收集器时,java堆的内存布局就与其他收集器有很大的差别,他将整个java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,他们都是一部分Region(不需要连续)的集合.
每个Regina大小都是一样的,可以是1M到32M之间的数值,但是必须保证是2的n次幂
如果对象太大,一个Region放不小[超过Region大小的50%],那么就会直接放到H中
设置Region大小:-XX:G1HeapRegionSize=M
所谓Garbage-Frist,其实就是优先回收垃圾最多的Region区域
(1)、分代收集(仍然保留了分代的概念)
(2)、空间整合(整体上属于"标记——整理"算法,不会导致空间碎片)
(3)、可预测的停顿,(比CMS更先进的地方在于能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒)
在这里插入图片描述
工作过程可以分为以下几步
在这里插入图片描述
4.8:ZGC
官网 :
JDK11新引入的ZGC收集器,不管是物理上还是逻辑上,ZGC已经不存在新老年代的概念了,会分为一个个page当进行GC操作时会对page进行压缩,因此没有碎片问题,只能在64位的Linux上使用,目前用的较少
(1)可以达到10ms以内的停顿时间要求
(2)支持TB级别的内存
(3)堆内存变大后停顿时间还是在10ms以内
在这里插入图片描述
5、垃圾收集器分类
一、串行收集器——>Serial和Serial Old
特点:只能有一个垃圾回收线程执行,用户线程暂停(适用于内存较小的嵌入式设备)
二、并行收集器[吞吐量优先]->Parallel Scanvenge、Parallel Old
特点:多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态(适用于科学计算、后台处理等若交互场景 )
三、并发收集器[停顿时间优先]->CMS、G1
特点:用户线程和垃圾收集线程同时执行(但并不一定是并行的,可能是交替执行的),垃圾收集线程在执行的时候不会停顿用户线程的运行(适用于相对时间有要求的场景,比如Web)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值