JVM(四)GC

一、什么是垃圾?

Java SE 8的文档中,有这样一句话: An object is considered garbage when it can no longer be reached from any pointer in the running program.
垃圾是指在程序运行过程中,没有被任何指针引用的对象。

二、为什么要有垃圾回收?

1、内存大小有限,总有一天内存会被占满,所以需要回收不再使用的内存空间。
2、除了回收,还需要对内存空间进行碎片管理。
内存碎片

如图所示,当无用的对象被回收后,会产生不连续的内存片段。如果要分配一个5个格子大小的内存,就需要将对象分开存储,降低运行效率;因此需要程序对碎片进行管理。

三、怎么回收垃圾?

1、标记算法
(1)引用计数法

引用计数法

原理: 在对象头中分配一个空间保存该对象被引用的次数;如果该对象被其它对象引用,引用计数加一,如果删除对该对象的引用,引用计数减一。当该对象的引用计数为0时,那么该对象就会可以被回收。

优点: 实现简单,判断效率高。

缺点: 如上图2、3行,如果出现循环引用,即obj1 -> obj2 -> obj3 -> obj1;则每个对象的引用数都是1,不会被回收,导致内存泄漏。

(2)GC Root可达性分析

可达性分析解决了对象循环引用的问题。

原理: 维护一个GC Root集合,然后遍历集合,从上到下搜索被GC Root链接的对象,未链接的对象认为是不可达的,可以被GC回收。

Java中,可作为GC Root的对象包括:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI(即Native方法)引用的对象。总结为一句话:一个引用,指向堆里边的对象,但自己不在堆中。

2、清除算法
(1)标记-清除法

标记-清除法

执行过程:

  • 标记阶段,使用GC Root可达性分析算法,从引用根结点开始遍历,标记所有被引用的对象。
  • 清除阶段,遍历堆内存,对未被标记的对象进行回收。

缺点:

  • 该算法需要两次遍历,尤其第二次要遍历全部堆内存,效率不高;
  • 会产生大量内存碎片。
(2)复制算法

复制算法

执行过程:

  • 将内存空间分为两块,每次只使用其中一块。垃圾回收时,从引用根结点开始遍历,将存活的对象复制到另一块区域,之后清除之前的内存块。

优点:

  • 对比标记-清楚算法,只需一次root节点遍历,无需第二次遍历全部堆内存,效率高;
  • 解决了内存碎片的问题。

缺点:

  • 只有一半的内存可用,造成了内存浪费;
  • 由于内存地址发生变化,所以需要额外开销维护引用关系;
  • 当存活的对象较多时,复制成本增加。
(3)标记-整理法

标记-整理法

执行过程:

  • 标记阶段,使用GC Root可达性分析算法,从引用根结点开始遍历,标记所有被引用的对象。
  • 整理阶段,移动所有存活的对象,按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。

优点:

  • 对比复制法,没有内存浪费。
  • 对比标记清除法,解决了内存碎片的问题。

缺点:

  • 需要额外的开销进行整理;
  • 由于内存地址发生变化,所以需要额外开销维护引用关系;

为什么先标记再整理,而不是一边标记一边整理?

  • 因为对象遍历顺序和内存摆放顺序可能不一致,如:一个对象摆放在内存的前面部分,但是需要等到最后才能遍历到这个对象。
(4)分代收集

JVM(三)堆与对象可知,JVM中堆被划分成两块区域:年轻代(young):老年代(old)= 1:2;年轻代又可以划分为Eden(伊甸园):From Survivor(幸存者):To Survivor (幸存者)= 8:1:1。这样分代的目的,就是为了优化GC。

堆区结构

  • 在年轻代,由于大多数对象都有朝生夕灭的特性,能够保留下来的对象很少。因此将年轻代分成三个区域,Eden用来生产对象,From 和 To 用来复制对象。
  • 老年代对象一般具有较长的存活时间,因此采用标记-整理算法,解决内存碎片问题。
(5)增量收集算法
  • 上述算法,每次进行GC时,都需要STW(Stop The World) ,导致在GC执行期间,程序得不到执行。
  • 如果GC期间,垃圾回收线程只收集一小片内存空间,然后切换到应用程序线程,交替进行,直到垃圾回收完毕,这样就可以减少GC停顿的情况。
(6)分区算法
  • 将整个堆空间划分为连续的不同小区间,每个小区间独立使用,独立回收。这样就可以控制一次回收多少个小区间,每次合理地回收若干个小区间,从而减少一次 GC 所产生的停顿。
3、垃圾回收器
名称收集算法工作区域可配合使用线程并发场合优缺点
Serial复制算法新生代CMS
————
Serial Old
单CPU
————
Client模式下
缺点:STW
————
优点:简单高效,没有线程开销
ParNew复制算法新生代CMS
————
Serial Old
多CPU
————
Server模式下
缺点:STW
————
优点:并行并发
Parallel Scavenge复制算法新生代CMS
————
Parallel Old
Client、Server都可以主要关注吞吐量,通过吞吐量设置控制停顿时间
Serial Old标记整理老年代Serial、ParNew、Parallel ScavengeClient模式下缺点:STW
Parallel Old复制算法老年代Parallel ScavengeClient、Server都可以主要关注吞吐量,通过吞吐量设置控制停顿时间
CMS
Concurretn Mark Sweep
标记清除算法老年代Serial、ParNew
————
Serial Old
Server端缺点:产生内存碎片
————
优点:并发收集
G1标记整理法新生代、老年代面向服务端优点:并行与并发
4、GC分类

在JVM标准中,GC按照回收区域分为两类:
(1)部分采集(Partial GC):

  • 年轻代采集(Minor GC/Young GC):只采集年轻代数据
  • 老年代采集(Old GC):只采集老年代数据
  • 混合采集(Mixed GC):采集年轻代、老年代部分数据

(2)整堆采集(Full GC):

  • 收集堆与方法区的所有垃圾
5、GC触发

(1)年轻代触发机制: 年轻代空间不足(Eden区满了)时,触发Minor GC。
(2)Full GC触发机制:

  • 调用System.gc()
  • 老年代空间不足时
  • 方法区空间不足时
6、三色标记过程
  • (1)初始时,所有对象都是白色;
  • (2)GC Roots引用的对象标为灰色;
  • (3)处理被标记为灰色的对象:
    < 3.1>当前对象直接引用到的对象标为灰色;
    < 3.2>当前对象标为黑色;
  • (4)重复上述步骤,直至没有灰色标记。
  • (5)白色标记的即为可回收对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值