轻松学习JVM(五)——垃圾回收器

上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃圾回收器,以便让自己的java程序性能到达最佳。

在介绍垃圾回收器之前,我们先回顾一下java堆的结构。

堆内存回顾

java堆内存结构包括:新生代和老年代,其中新生代由一个伊甸区和2个幸存区组成,2个幸存区是大小相同,完全对称的,没有任何差别。我们把它们称为S0区和S1区,也可以称为from区和to区。

JVM的垃圾回收主要是针对以上堆空间的垃圾回收,当然其实也会针对元数据区(永久区)进行垃圾回收,在此我们主要介绍对堆空间的垃圾回收。

下面我们介绍几种垃圾回收器:

串行收集器

顾名思义,串行收集器就是使用单线程进行垃圾回收。对新生代的回收使用复制算法,对老年代使用标记压缩算法,这也和我们上一篇介绍的算法优势是相吻合的。

串行收集器是最古老最稳定的收集器,尽管它是串行回收,回收时间较长,但其稳定性是优于其他回收器的,综合来说是一个不错的选择。要使用串行收集器,可以在启动配置时加上以下参数:

-XX:+UseSerialGC

串行回收器的执行流程如下所示:

执行垃圾回收时,应用程序线程暂停,GC线程开始(开始垃圾回收),垃圾回收完成后,应用程序线程继续执行。注意:在GC线程运行过程中使用单线程进行串行回收。

并行回收器

并行回收器你可能已经猜到就是使用多线程并行回收,不过这里需要注意的是,针对新生代和老年代,是否都使用并行,有不同的回收器选择:

1、 ParNew回收器

这个回收器只针对新生代进行并发回收,老年代依然使用串行回收。回收算法依然和串行回收一样,新生代使用复制算法,老年代使用标记压缩算法。在多核条件下,它的性能显然优于串行回收器,如果要使用这种回收器,可以在启动参数中配置:

-XX:+UseParNewGC

如果要进一步指定并发的线程数,可以配置一下参数:

-XX:ParallelGCThreads

ParNew回收器的流程如下图所示:

在进行垃圾回收时应用程序线程依然被暂停,GC线程并行开始执行垃圾回收,垃圾回收完成后,应用程序线程继续执行。

2、 Parallel回收器

依然是并行回收器,但这种回收器有两种配置,一种类似于ParNEW:新生代使用并行回收、老年代使用串行回收。它与ParNew的不同在于它在设计目标上更重视吞吐量,可以认为在相同的条件下它比ParNew更优。要使用这种回收器可以在启动程序中配置:

-XX:+UseParallelGC

Parallel回收器另外一种配置则不同于ParNew,对于新生代和老年代均适应并行回收,要使用这种回收器可以在启动程序中配置:

XX:+UseParallelOldGC

Parallel回收器的流程和ParNew的流程是一致的:

在进行回收时,应用程序暂停,GC使用多线程并发回收,回收完成后应用程序线程继续运行。

CMS回收器

CMS回收器: Concurrent Mark Sweep,并发标记清除。注意这里注意两个词:并发、标记清除。

并发表示它可以与应用程序并发执行、交替执行;标记清除表示这种回收器不是使用的是标记压缩算法,这和前面介绍的串行回收器和并发回收器有所不同。需要注意的是CMS回收器是一种针对老年代的回收器,不对新生代产生作用。这种回收器优点在于减少了应用程序停顿的时间,因为它不需要应用程序完成暂定等待垃圾回收,而是与垃圾回收并发执行。要执行这种垃圾回收器可以在启动参数中配置:

-XX:+UseConcMarkSweepGC

CMS回收机运行机制非常复杂,我们简单的将他的运行流程分为以下几步:

初始标记

标记从GC Root可以直接可达的对象;

并发标记(和应用程序线程一起)

主要标记过程,标记全部对象;

重新标记

由于并发标记时,用户线程依然运行,因此在正式清理前,再做依次重新标记,进行修正。

并发清除(和用户线程一起)

基于标记结果,直接清理对象。

流程如下图所示:

从上图可以看到标记过程分三步:初始标记、并发标记、重新标记,并发标记是最主要的标记过程,而这个过程是并发执行的,可以与应用程序线程同时进行,初始标记和重新标记虽然不能和应用程序并发执行,但这两个过程标记速度快,时间短,所以对应用程序不会产生太大的影响。最后并发清除的过程,也是和应用程序同时进行的,避免了应用程序的停顿。

CMS的优点显而易见,就是减少了应用程序的停顿时间,让回收线程和应用程序线程可以并发执行。但它也不是完美的,从他的运行机制可以看出,因为它不像其他回收器一样集中一段时间对垃圾进行回收,并且在回收时应用程序还是运行,因此它的回收并不彻底。这也导致了CMS回收的频率相较其他回收器要高,频繁的回收将影响应用程序的吞吐量。

G1回收器

G1回收器是jdk1.7以后推出的回收器,试图取代CMS回收器。

不同于其他的回收器、G1将堆空间划分成了互相独立的区块。每块区域既有可能属于老年代、也有可能是新生代,并且每类区域空间可以是不连续的(对比CMS的老年代和新生代都必须是连续的)。这种将老年代区划分成多块的理念源于:当并发后台线程寻找可回收的对象时、有些区块包含可回收的对象要比其他区块多很多。虽然在清理这些区块时G1仍然需要暂停应用线程、但可以用相对较少的时间优先回收包含垃圾最多区块。这也是为什么G1命名为Garbage First的原因:第一时间处理垃圾最多的区块。要使用G1回收器需要在启动是配置以下参数:

-XX:+UseG1GC

G1相对CMS回收器来说优点在于:

1、因为划分了很多区块,回收时减小了内存碎片的产生;

2、G1适用于新生代和老年代,而CMS只适用于老年代。

小结

本文简要介绍了JVM中的垃圾回收器,主要包括串行回收器、并行回收器以及CMS回收器、G1回收器。他们各自都有优缺点,通常来说你需要根据你的业务,进行基于垃圾回收器的性能测试,然后再做选择。下面给出配置回收器时,经常使用的参数:

-XX:+UseSerialGC:在新生代和老年代使用串行收集器

-XX:+UseParNewGC:在新生代使用并行收集器

-XX:+UseParallelGC :新生代使用并行回收收集器,更加关注吞吐量

-XX:+UseParallelOldGC:老年代使用并行回收收集器

-XX:ParallelGCThreads:设置用于垃圾回收的线程数

-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器

-XX:ParallelCMSThreads:设定CMS的线程数量

-XX:+UseG1GC:启用G1垃圾回收器

深入理解JVM(五)——垃圾回收器的更多相关文章

  1. 深入理解JVM一垃圾回收器

    上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...

  2. 深入理解JVM(五) -- 垃圾回收算法

    上篇文章我们了解到哪些内存区域和哪些对象可以被回收,这篇文章我们就来了解一下具体的垃圾回收算法的思路,不讨论具体的实现. 一 最基础算法 标记-清除(Mark-Swap) 为什么说他是最基础的算法,因 ...

  3. 【JVM】垃圾回收器总结(2)——七种垃圾回收器类型

    七种垃圾回收器类型 GC的约定参数 DefNew——Default New Generation Tenured——Serial Old ParNew——Parallel New Generation ...

  4. JVM学习--(五)垃圾回收器

    上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...

  5. 深入理解JVM一垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. 一.stop the world 在介绍 ...

  6. 深入理解JVM——关于垃圾回收

    关于垃圾回收 仿佛来自上海居委会大妈的灵魂拷问:“你是什么垃圾?” 不 今天我们要说的是JVM的垃圾回收 假如我是一个“人”类的“对象”,也和人的生命一样必有一死,可是“我真的还想再活500年~~”, ...

  7. JVM七大垃圾回收器下篇G1(Garbage First)

    G1回收器:区域化分代式 既然我们已经有了前面几个强大的GC,为什么还要发布Garbage First (G1)GC?  原因就在于应用程序所应对的业务越来越庞大.复杂,用户越来越多,没有GC就不能保 ...

  8. 面试官:说一下JVM常用垃圾回收器的特点、优劣势、使用场景和参数设置

    今天去看牙医,他问我年级轻轻牙齿怎么磨损这么严重?我说,没有人点赞的这些年,我都是咬着牙过来的. Java中的垃圾回收器几乎是面试中的必考点,无论是面试初级,中级还是高级,总免不了要问一问垃圾回收器的 ...

  9. JVM(3) 垃圾回收器与内存分配策略

    文章内容摘自:深入理解java虚拟机 第三章   对象已死? 1. 引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0 ...

  10. 第三篇:jvm之垃圾回收器

    一.Serial收集器 新生代收集器,在垃圾回收时,必须暂停其他所有的工作线程.即Stop-The-World. 评价:老而无用,食之无味,弃之可惜. 二.ParNew收集器 新生代收集器,seria ...

随机推荐

  1. 【Jquery系列】prop和attr区别

    问题描述 由于prop(property的缩写)和attr(attribute的缩写)翻译成汉语,均有“特性.属性”等意思的原因,导致大家容易混淆分不清,本篇文章将试图从英文含义,中文含义和Jquer ...

  2. UI性能优化

    我的思路 在移动设备上打开UI界面卡顿,等待时间长,页面白块,等等体验是很不好的.本文记录我在工作中解决UI卡顿的方法. 我主要从以下方面入手 资源量 界面打开做的操作 界面自身的逻辑 IO的读写(包 ...

  3. 分布式:ACID, CAP, BASE

    本文主要讲述分布式系统开发的一些相关理论基础. 一.ACID ACID是一系列对系统中数据进行访问与更新的操作所组成的一个程序执行的逻辑单元,狭义上的事务特指数据库事务. 1.Atomic原子性 事务 ...

  4. Struts2框架(3)---Action类的3种书写方式

    Action类的3种书写方式 本文主要写有关写Action类的3种书写方式: (1)第一种 Action可以是POJO (简单模型对象)  不需要继承任何父类 也不需要实现任何接口 (2)实现Acti ...

  5. OpenCASCADE构造一般曲面

    OpenCASCADE构造一般曲面 eryar@163.com Abstract. 本文主要介绍常见的曲面如一般柱面(拉伸曲面).旋转面在OpenCASCADE中的构造方法,由此思考一般放样算法的实现 ...

  6. DataBase MongoDB高级知识

    MongoDB高级知识 一.mongodb适合场景: 1.读写分离:MongoDB服务采用三节点副本集的高可用架构,三个数据节点位于不同的物理服务器上,自动同步数据.Primary和Secondary ...

  7. C:宏定义的一些格式(怕忘记)

    现在还没怎么用到宏定义,但以后肯定会经常用的,写下这盘,以后忘记了可以温故.首先宏定义必须写在函数之外,其作用域从宏定义命令起到源程序结束,也就是说一但定义系统就会分配内存,想让它结束用“#undef ...

  8. C#中&与&&的区别

    c#&是什么意思? 看过一些文章,关于这个的简单而容易被忽略的语法,说的总有点瑕疵. 贴代码15秒之内应该能知道c#中一个&和两个&&的区别,开始计数了........ ...

  9. PredictionIO+Universal Recommender快速开发部署推荐引擎的问题总结(2)

    1, 对Universal Recommender进行pio build成功,但是却提示No engine found Building and delpoying model [INFO] [Eng ...

  10. Fragment生命周期及实现点击导航图片切换fragment,Demo

    PS:Fragment简介 Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 当然现在他仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会 ...