GC垃圾回收机制

1 垃圾回收对象

Java 堆是垃圾收集器管理的主要区域,因此也被称作GC 堆(Garbage Collected Heap).从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代:再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。进一步划分的目的是更好地回收内存,或者更快地分配内存。

2 垃圾回收模型

在这里插入图片描述

  1. Eden区位于Java堆的年轻代,是新对象分配内存的地方,由于堆是所有线程共享的,因此在堆上分配内存需要加锁。而Sun JDK为提升效率,会为每个新建的线程在Eden上分配一块独立的空间由该线程独享,这块空间称为TLAB(Thread Local Allocation Buffer)。在TLAB上分配内存不需要加锁,因此JVM在给线程中的对象分配内存时会尽量在TLAB上分配。如果对象过大或TLAB用完,则仍然在堆上进行分配。如果Eden区内存也用完了,则会进行一次Minor GC(young GC)。

  2. Survival区与Eden区相同都在Java堆的年轻代。Survival区有两块,一块称为from区,另一块为to区,这两个区是相对的,在发生一次Minor GC后,from区就会和to区互换。在发生Minor GC时,Eden区和Survivalfrom区会把一些仍然存活的对象复制进Survival to区,并清除内存。Survival to区会把一些存活得足够旧的对象移至年老代。 对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了

  3. 年老代里存放的都是存活时间较久的,大小较大的对象,因此年老代使用标记整理算法。当年老代容量满的时候,会触发一次Major GC(full GC),回收年老代和年轻代中不再被使用的对象资源。

GC是统计学测算出当内存使用超过98%以上时,内存就应该被minor gc时回收一次。但是实际应用中,我们不能较真的只给 他们留下2%,换句话说当内存使用达到98%时才GC 就有点晚了,应该是多一些预留10%内存空间,这预留下来的空间我们称为S区(有两个s区 s1 和 s0),S区是用来存储新生代GC后存活下来的对象,而我们知道新生代GC算法使用的是复制回收算法。

所以我们实际GC发生是在,新生代内存使用达到90%时开始进行,复制存活的对象到S1区,要知道GC结束后在S1区活下来的对象,需要放回给S0区,也就是对调(对调是指,两个S区位置互换,意味着再一次minor gc 时的区域 是eden 加,上一次存活的对象放入的S区),既然能对调,其实就是两个区域一般大。这也是为什么会再有个10%的S0区域出来。这样比例就是8:1:1了!!(80%:s1:s0=80%:10%:10%=8:1:1)这里的eden区(80%) 和其中的一个 S区(10%) 合起来共占据90%,GC就是清理的他们,始终保持着其中一个 S 区是空留的,保证GC的时候复制存活的对象有个存储的地方。

3 垃圾回收触发机制

  1. 创建对象的时候,对象需要有内存空间,也是需要为这个对象进行内存空间的申请

  2. 首先判断伊甸园区(Eden)是否有内存空间,如果有就将对象保存到伊甸园区

  3. 如果空间不足,则自动执行Minor GC(从年轻代回收内存),将Eden区不活跃的对象清理,清理之后继续判断内存是否充足,若充足则分配内存

  4. 如果执行过后,Eden区仍然内存不足,那就进行存活区判断,如果存货区有内存空间,则将Eden取的部分活跃对象保存到存活区,随后继续判断Eden区内存空间是否充足,如果进行内存分配

  5. 如果存活期没有内存空间了,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区

  6. 当old区空间不够时,这个时候会产生Major GC(Full GC)

  7. 完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";

手动调用system.gc 提醒需要触发,但是不能保证执行。

4 垃圾回收常用算法

4.1 区分可回收对象算法

4.1.1 引用计数法:

给对象添加一个引用计数器,当有地方引用的时候,计数器就+1,引用失效就-1;任何时候当计数器为0,那么这个对象就是可以被回收的。该方法实现简单,效率也高,但是并没有被主流的虚拟机采用,因为很难解决对象互相循环引用问题。

4.1.2 可达性分析算法:

这个的基本思想就是通过一系列的“GC Roots”作为对象的起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

4.2 垃圾回收算法

4.2.1.1 标记清除算法

清除算法分为标记和清除两个阶段。该算法首先从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象并进行回收。
效率问题:标记和清除两个过程的效率都不高;
空间问题:标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,因此标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

4.2.1.2 复制算法

复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于对象存活率低的场景,比如新生代。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。(新生代)

4.2.1.3 标记整理算法

复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。标记整理算法的标记过程类似标记清除算法,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,类似于磁盘整理的过程,该垃圾回收算法适用于对象存活率高的场景(老年代)。

5 常用GC种类

  1. serial new收集器
    单线程收集器,收集时会停止其他任务执行,采用复制算法
  2. serial Old收集器
    单线程收集器,收集时会停止其他任务执行,采用标记整理算法
  3. parallel new 收集器
    多线程收集器,收集时会停止其他任务执行,采用复制算法
  4. parallel old 收集器
    多线程收集器,收集时会停止其他任务执行,采用标记整理算法
  5. CMS收集器
    以获取最短回收停顿时间【也就是指Stop The World的停顿时间】为目标,多数应用于互联网站或者B/S系统的服务器端上。其中“Concurrent”并发是指垃圾收集的线程和用户执行的线程是可以同时执行的。采用标记清除算法,初始化标记,并发标记,重新标记,并发清除,收集结束会产生大量的内存碎片
  6. G1收集器
    为了实现STW的时间可预测,首先要有一个思想上的改变。G1将堆内存“化整为零”,将堆内存划分成多个大小相等独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。采用标记整理算法,初始标记,并发标记,最终标记,筛选标记,不会产生内存碎片
  7. 2GC收集器
    以低延迟为首要目标的一款垃圾收集器。它是基于动态Region内存布局,(暂时)不设年龄分代,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的收集器。在JDK 11新加入,还在实验阶段,主要特点是:回收TB级内存(最大4T),停顿时间不超过10ms。
  8. Shenandoah收集器,
    Shenandoah是一款只有OpenJDK才会包含的收集器
    1 支持并发的整理算法,Shenandoah的回收阶段可以和用户线程并发执行;
    2 Shenandoah 目前不使用分代收集,也就是没有年轻代老年代的概念在里面了;
    3 Shenandoah 摒弃了在G1中耗费大量内存和计算资源去维护的记忆集,改用名为“连接矩阵”(Connection Matrix)的全局数据结构来记录跨Region的引用关系,降低了处理跨代指针时的记忆集维护消耗,也降低了伪共享问题的发生概率。
  9. Parallel Scavenge垃圾收集器
    以高吞吐量为目标,即减少垃圾收集时间(就是每次垃圾收集时间短,但是收集次数多),让用户代码获得更长的运行时间。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值