摘要

垃圾收集器(GC,Garbage Collector):自动化的内存管理工具,垃圾收集器主要做以下几种工作:

  • 在新生代中给新对象分配内存,并将老对象放到老年代中去管理。(Allocating objects to a young generation and promoting aged objects into an old generation.)
  • Java HotSpot VM在Java堆内存占用率超过默认阈值时触发标记阶段,标记阶段将通过并行标记的方式在老年代中寻找存活的对象。(Finding live objects in the old generation through a concurrent (parallel) marking phase. The Java HotSpot VM triggers the marking phase when the total Java heap occupancy exceeds the default threshold.)
  • 通过并行复制的算法压缩存活的对象从而恢复可用内存。(Recovering free memory by compacting live objects through parallel copying.)

    如何选择垃圾收集器才能使应用的性能达到最优?HotSpot团队都难以对这个问题给出完美的答案。一般而言,暂停应用程序进行垃圾回收的频率越低且每次垃圾回收的时间越短,应用程序的性能就会越高。但是拥有许多大数据对象的多线程高事务率的大型应用的垃圾回收很难同时满足以上两点。

    阿姆达定理(系统中对某一部件采用更快执行方式所能获得的系统性能改进程度,取决于这种执行方式被使用的频率,或所占总执行时间的比例。)说明,给定问题的并行加速度由问题的顺序执行部分限制其性能。其意为者部分工作并不能完美的并行化,只能串行的执行。在JAVA平台也受此定理的影响,JAVA SE 1.4之前并不支持并行垃圾回收,故垃圾收集器在多处理器下对性能的影响随程序的并行化而增长。

引言

小至简单的 public static void main 程序,大至拥有数百台服务器集群的大型WEB服务,全世界目前有几十亿部设备正在使用JAVA。为了支持这种多样化的部署,Java HotSpot虚拟机(Java HotSpot VM)提供了多个垃圾收集器,每个垃圾回收器被设计为满足不同的需求。JAVA应用程序可以根据自身运行的类型(调试版或生产版)与载体物理机的配置情况,自动的去选择合适的垃圾收集器。但当需求上需要我们写出更加高性能的应用程序时,JAVA的默认配置就很难再满足我们的需求。此时便需要作为开发或运维人员的你通过设置一些JVM参数,明确的指定垃圾收集器等方式,来达到性能需求上所指明的条件。

在阅读本文之前,我希望你已经读过我的上篇文章JVM虚拟机-垃圾回收算法,对常见的垃圾回收算法及其在HotSpot虚拟机下的实现有了解,如果说垃圾回收算法是理论基础,那么本文所介绍的垃圾收集器就是JVM垃圾收集的具体实现。另外希望你在工作或研究的过程中感受过JAVA默认的垃圾回收机制给你带来过性能上的压力,因为只有亲身的经历过,才能感受到了解垃圾收集器的机制的重要性。

本文会以JAVA8版本的HotSpot虚拟机为基础环境逐个的介绍每个垃圾收集器的实现原理并分析其优缺点,简略的探讨一下什么样的应用在什么样的环境下应该选用哪种垃圾收集器。本文的目标是能够帮助读者对应用程序进行JVM调优,做出高性能的应用。

本文着重对CMS和G1两款垃圾收集器进行介绍分析。

基础

HotSpot虚拟机提供了三种大类的垃圾收集器,每种垃圾收集器都有不同的特征和性能表现。简单描述如下:

  • 串行类垃圾收集器( serial collector):
    串行类垃圾收集器是最受争议的垃圾收集器,串行垃圾收集器使用单个线程完成所有的垃圾收集工作。其工作时不需要与其它的线程进行交互,所以垃圾回收的效率是很高的。串行类垃圾收集器尤其适合单CPU的硬件平台上使用,且在使用数据集小于100MB的多CPU硬件平台上也能取得很好的效果。HotSpot在Client模式下默认使用串行垃圾收集器,在其它环境下也可以通过使用 -XX:+UseSerialGC 参数来明确指定使用串行垃圾收集器。

  • 并行垃圾收集器(Parallel Collector):
    并行垃圾收集器又被称为吞吐量优先垃圾收集器(Throughput Collector),通常我们所指的吞吐量优先垃圾收集器指的都是适用于新生代的 Parallel Scavenge 垃圾收集器。并行垃圾收集器能够显著的减少多CPU环境下中型或大型应用垃圾收集所消耗的时间,HotSpot Server版本默认使用的使用的垃圾收集器就是并行垃圾收集器。通过启动虚拟机的时候指定参数 -XX:+UseParallelGC 可以手动指定年轻代使用吞吐量优先收集器。与年轻代相呼应的还有老年代并行垃圾收集器(Oracle 称其为 Parallel compaction 意为并行压缩),当使用参数 -XX:+UseParallelGC 时,JVM老年代的默认开启 Parallel compaction ,同时也可以通过参数 -XX:-UseParallelOldGC 来手动开启。

    • 并发垃圾收集器(Concurrent Collector):
      从字面上理解,并发垃圾收集器的意思是让用户线程和垃圾回收线程并发运行。其在大中型应用系统中并发垃圾收集器工作的过程中仅仅有很短的 ‘Stop the world’ ,且相对于并行垃圾收集器能够大幅度的减小系统响应时间(可能以牺牲系统吞吐量为代价)。JAVA8版本的HotSpot虚拟机下目前有两款并发收集器,CMS垃圾收集器(通过参数 XX:+UseConcMarkSweepGC 开启)和G1(通过参数 -XX:+UseG1GC 开启)。

探索

引用

本文是对JVM垃圾收集器的学习笔记,笔记的内容并非是原创,而是大量参考其它资料。在写作本文的过程中引用了以下资料,为为在此深深谢过以下资料的作者。

  1. 《The Java® Virtual Machine Specification · Java SE 8 Edition》
  2. 《深入理解Java虚拟机:JVM高级特性与最佳实践/周志明著.——2版.——北京:机械工业出版社,2013.6》
  3. 《Java Platform,Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide》

    非原创声明

    本文并非我的原创文章,而是我学习jvm时的笔记。文中的材料与数据大部分来自于其它资料,详细请查看本文的引用章节。

关于

本项目和文档中所用的内容仅供学习和研究之用,转载或引用时请指明出处。如果你对文档有疑问或问题,请在项目中给我留言或发email到
weiwei02@vip.qq.com 我的github:
https://github.com/weiwei02/ 我相信技术能够改变世界 。