Java 虚拟机(四)垃圾收集算法

栏目: 服务器 · 发布时间: 7年前

内容简介:Java 虚拟机(四)垃圾收集算法

相关文章

Java虚拟机系列

前言

在本系列上一篇文章中我讲到了垃圾标记算法,垃圾被标记后,GC就会对垃圾进行收集,垃圾收集有很多种算法,这篇文章就来介绍常用的垃圾收集算法的思想。

1.标记-清除算法

标记-清除算法(Mark-Sweep)是一种常见的基础垃圾收集算法,它将垃圾收集分为两个阶段:

  • 标记阶段:标记出可以回收的对象。
  • 清除阶段:回收被标记的对象所占用的空间。

标记-清除算法之所以是基础的,是因为后面讲到的垃圾收集算法都是在此算法的基础上进行改进的。标记-清除算法的执行的过程如下图所示。

Java 虚拟机(四)垃圾收集算法

标记-清除算法主要有两个缺点,一个是标记和清除的效率都不高,另一个从上图就可以看出来,就是容易产生大量不连续的内存碎片,碎片太多可能会导致后续没有足够的连续内存分配给较大的对象,从而提前触发新的一次垃圾收集动作。

2.复制算法

为了解决标记-清除算法的效率不高的问题,产生了复制算法。它把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾收集时,遍历当前使用的区域,把存活对象复制到另外一个区域中,最后将当前使用的区域的可回收的对象进行回收。复制算法的执行过程如下图所示。

Java 虚拟机(四)垃圾收集算法

这种算法每次都对整个半区进行内存回收,不需要考虑内存碎片的问题,代价就是使用内存为原来的一半。

复制算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很少,复制算法的效率就会很高。由于绝大多数对象的生命周期很短,并且这些生命周期很短的对象都存于新生代中,所以复制算法被广泛应用于新生代中,关于新生代中复制算法的应用,会在后面的分代收集算法中详细介绍。

3.标记-压缩算法

在新生代中可以使用复制算法,但是在老年代就不能选择复制算法了,因为老年代的对象存活率会较高,这样会有较多的复制操作,导致效率变低。标记-清除算法可以应用在老年代中,但是它效率不高,在内存回收后容易产生大量内存碎片。因此就出现了一种标记-压缩算法(Mark-Compact)算法,与标记-清除算法不同的是,在标记可回收的对象后将所有存活的对象压缩到内存的一端,使他们紧凑的排列在一起,然后对端边界以外的内存进行回收。回收后,已用和未用的内存都各自一边,如下图所示。

Java 虚拟机(四)垃圾收集算法

标记-压缩算法解决了标记-清除算法效率低和容易产生大量内存碎片的问题,它被广泛的应用于老年代中。

4.分代收集算法

Java堆区的空间划分

Java 虚拟机中,各种对象的生命周期会有着较大的差别,大部分对象生命周期很短暂,少部分对象生命周期很长,有的甚至和应用程序以及Java虚拟机的运行周期一样长。因此,应该对不同生命周期的对象采取不同的收集策略,根据生命周期长短将它们分别放到不同的区域,并在不同的区域采用不同的收集算法,这就是分代的概念。

现在主流的Java虚拟机的垃圾收集器都采用分代收集算法(Generational Collection)。Java堆区基于分代的概念,分为新生代(Young Generation)和老年代(Tenured Generation),其中新生代再细分为Eden空间、From Survivor空间和To Survivor空间。因为Eden空间大多对象生命周期很短,所以新生代的空间划分并不是均分的,HotSpot虚拟机默认Eden空间和两个Survivor空间的所占的比例为8:1。

分代收集

根据Java堆区的空间划分,垃圾收集的类型分为两种,它们分别是:

  • Minor Collection:新生代垃圾收集。
  • Full Collection:对新生代、老年代和永久代(JDK8 取消永久代,Full Collection扫描不到替代永久代的元空间)进行收集,又可以称作Majjor Collection。它的收集频率较低,耗时较长。

当执行一次Minor Collection时,Eden空间的存活对象会被复制到To Survivor空间,并且之前经过一次Minor Collection并在From Survivor空间存活的仍年轻的对象也会复制到To Survivor空间。

有两种情况Eden空间和From Survivor空间存活的对象不会复制到To Survivor空间,而是晋升到老年代。一种是存活的对象的分代年龄超过-XX:MaxTenuringThreshold(用于控制对象经历多少次Minor GC才晋升到老年代)所指定的阈值。另一种是To Survivor空间容量达到阈值。

当所有存活的对象被复制到To Survivor空间,或者晋升到老年代,也就意味着Eden空间和From Survivor空间剩下的都是可回收对象,如下图所示。

Java 虚拟机(四)垃圾收集算法

这时GC执行Minor Collection,Eden空间和From Survivor空间都会被清空,而存活的对象都存放在To Survivor空间。

接下来将From Survivor空间和To Survivor空间互换位置,也就是此前的From Survivor空间成为了现在的To Survivor空间,每次Survivor空间互换都要保证To Survivor空间是空的,这就是复制算法在新生代中的应用。在老年代则采用了标记-压缩算法。

在HotSpot中,基于分代的概念,GC使用的回收算法针对新生代和老年代的特点,采用不同的垃圾收集算法。

参考资料

《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》第二版

《Java虚拟机精讲》

《HotSpot实战》

欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多 成体系 的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。

Java 虚拟机(四)垃圾收集算法

以上所述就是小编给大家介绍的《Java 虚拟机(四)垃圾收集算法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Flash ActionScript 3.0从入门到精通

Flash ActionScript 3.0从入门到精通

章精设、胡登涛 / 清华大学出版社 / 2008-10-1 / 69.00元

Flash ActionScript 3.0的出现,不仅从形式上改变了ActionScript,而且从本质上改变了ActionScript,使ActionScript 3.0成为了真正的面向对象编程语言。 本书从最简单的编程知识出发,带领读者走进编程的大门,是一本不可多得的ActionScript 3.0入门书。本书在注重基础的同时,从更高的层次来介绍ActionScript 3.0的面向对......一起来看看 《Flash ActionScript 3.0从入门到精通》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具