1、简介

对于Java developer来说,了解JVM GC工作原理能够帮助我们开发出更优秀的应用,同时在处理JVM瓶颈时能够更加自由。在最近一年的应用开发中能体会到这些知识带来的好处,并且让我们的应用在较大规模的并发时能够良好的工作。

本文部分知识和图片来源于书籍《Java Performance》 - Charlie Hunt & Binu John 著,该书全面讲解了Java 应用的性能分析、优化点与JVM原理等知识,本文(以及稍候的一些文章)只包含 GC collector 的部分知识,另外也只是针对常用的HotSpot JVM,当然很多知识是相通的。

2、 JVM Overview

上图为JVM的概要构架,主要分为 VM Runtime、GC Collector以及 JIT Compiler,其中我们能通过配置干预的只有GC 和 JIT(通过-server 和 -client选择不同的 JIT Compiler,其中-server在启动完成后具有更好的性能,但是花费启动时间稍长些 -- 虽然我们没明显感觉)。

下图则是JVM中内存分区模型,即分为 Heap area, method area, VM stack, native method stack和PC register。

本文只关注GC collector所涉及的Heap area 和 Method area, 其他的可另外了解。

3、Garbage Collections

在GC 中,最 ”引人入胜“ 的是 "stop-the-world",它在目前所实现的GC算法中都将出现,它出现的时候JVM 所承载的应用程序将停止执行,也就是说我们的应用中的所有线程将停止响应,直到 "stop-the-world" 完成工作。

HotSpot VM把 Heap Area分为 young generation 和 old generation两个物理区域,也就是我们常翻译为:年轻代和年老代。它们有以下特征:

1. 年轻代:大部分对象在这里分配,通常来说会进行比较小但是比较频繁的回收,花费时间较短。

2. 年老代:内存相对较大,对象会相对保留比较长的时间,大对象也一般分配在此,占用空间上升缓慢并且回收频率低,"stop-the-world" 会在它回收时发生,花费较长的时间。

如下图中,对象在年轻代分配,经过一些时间后可能会被移到年老代。其中的permanent generation为持久区,主要存放元数据如class data structures, interned strings等信息。GC 重点在于 young gen 和 old gen的回收。

3.1 Young generation

Young generation 有更细的划分,分为 Eden 和 2个survivor space(即幸存区) 如下图:

1. The eden: 大部分新对象在这里分配,有些大对象直接在年老区分配,这个区域进行回收后很多情况下会变空。

2. The two survivor spaces:Eden 区满时会将仍然存活的对象复制至其中一个survivor区,当这个区又满时将复制至另外一个survivor区,如下图:

3.2 Garbage Collectors

HotSpot 目前有三种可用的回收器: Serial GC, Parallel GC 和 Concurrent Mark-Sweep(CMS GC),回收类型分为mirror GC 和 major GC(也叫做Full GC),mirror GC针对young generation,major GC针对 old generation。

注:查询应用使用的垃圾回收与内存分配情况使用:jmap -heap [PID],其中PID为进程ID,稍候的文章会可能会有示例。

3.2.1 Serial GC

当Java 应用启动时如果加入-client 参数则使用这个回收器(如果不指定会根据官方的判断方法(如CPU核数,内存大小等)来决定使用 -server还是 -client,详情请查询官方资料),在目前的硬件配置来说,指定-server是大部分场景所需。

该回收器的特点是单线程回收(在这个多核时代明显很少被选择),mirro GC和major GC都需要暂停应用(即stop-the-world)

,如下图:

3.2.2 Parallel GC

在parallel GC 中,minor 和 full GC 都是并行的,可使用多核并行回收,可指定使用多少线程,能很好改善应用吞吐量,一般的机器配置中,如果不指定所使用的GC collector,一般默认为 Parallel GC,它符合大多数应用场景。如下图:

3.2.3 CMS GC

该回收器的出现主要应对低响应延时的应用场景,即  stop-the-world 一旦发生,应用将停止响应直到它工作完成,这情况在很多WEB、电信或银行应用中尤为关键。虽然 major GC很少发生,但是一旦发生将耗时较长,特别是在Heap很大的时候(也就是我们为什么不能让Heap分配很大的原因,适当即可,可有效分散GC暂停的时间使得不会感到明显卡顿)。

CMS GC 旨在减少应用的响应时间(但会牺牲一些吞吐量),由于延长了GC的工作周期,所以有更大的heap区要求(在marking pause阶段仍然允许分配内存),它同时具有更复杂的算法,CMS GC在管理 young generation方面与 Serial/Parallel GC一样(通过参数指定,稍候的文章中会有详解),在管理 old generation 采用2个周期来回收以减少应用暂停时间,如下图:

大致动作描述分为:

1. Initial mark,标记在old generation之外的所有可直接抵达的对象(如静态对象、线程栈等)。

2. Concurrent marking phase,在这个阶段标记所有可抵达的(直接或间接)存活对象,在这个阶段应用是不需要停止的,标记线程和应用线程同时工作。

3. Concurrent pre-cleaning为了减轻Remark pause步骤的工作,如访问在making phase阶段被更改的引用,虽然Remark pause还是会做这工作,但是它能显著地减少Remark pause的持续时间。

4. Remark pause,由于应用工作时会不停地更新引用,所以最后还是需要暂停应用来彻底标记,这步骤重新检查前一步骤(Concurrent marking phase)到暂停这时间段内更新的引用。

5. Concurrent sweeping phase,这步骤已经知道了所有在old generation存活的对象,将重新整理内存和释放不可达对象(如下图b所示),释放后标识空闲空间,但他们是不连续的(Serial和parallel GC 则采用下图a的压缩方式),所以将导致在old generation分配内存代价比较昂贵。Marking pause阶段能保证标记在这阶段存活的对象,但不能保证所有不可达的对象能被清理,如果本次回收不能清理,则下次Full GC的时候将被回收。

最后谈内存碎片问题:由于缺少内存压缩将使得内存碎片化,CMS 提供压缩周期,这周期也是stop the world,和serial、parallel GC 相似。使用-XX:CMSFullGCsBeforeCompaction参数指定full GC 多少次后进行内存压缩,默认为0,一般可设置为1,稍候的文章中会有相关GC的参数详解。

3.2.4 The Garbage-First GC

G1 GC 未来将作为 CMS GC 的一种替代(在Java 6 update 20 or later和 Java 7中才具有), 它可指定GC导致的应用停止时间,有不同的内存分布,提高应用实时性,但该GC 未经过大量的生产环境应用验证,目前只作为实验性特征使用。

关于这几个GC行为对比如下图:

4. 总结

JVM 调优主要在3点:

1. 选择合适的 GC collector.

2. 指定合适的 heap area大小.

3. 指定young generation的比例(或大小),它影响到 Full GC发生的频率以及应用暂停时间.

Java GC - 垃圾回收机制的更多相关文章

  1. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  2. 乐字节Java|GC垃圾回收机制、package和import

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  3. Android内存优化3 了解java GC 垃圾回收机制1

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  4. Android内存优化5 了解java GC 垃圾回收机制3

    引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...

  5. JAVA gc垃圾回收机制

    一.GC概要   JVM堆相关知识     为什么先说JVM堆?     JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方 ...

  6. 转载 JAVA gc垃圾回收机制

    thanks:https://m.oschina.net/u/123553 一.GC概要 JVM堆相关知识    为什么先说JVM堆?    JVM的堆是Java对象的活动空间,程序中的类的对象从中分 ...

  7. java GC垃圾回收机制G1、CMS

    CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间.对于要求服务器响应速度的应用上,这种垃圾回收器非常适合.在启动JVM参数加上-XX:+UseConcMa ...

  8. Android内存优化4 了解java GC 垃圾回收机制2 GC执行finalize的过程

    1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数 ...

  9. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

随机推荐

  1. SICP-1.4-函数设计

    何为好的函数 每个函数只完成一个工作 不要做重复工作 如果你多次复制一段代码块,说明你应该进行函数抽象了 定义一般化函数 避免特例化 函数说明 一般通过三引号说明 help调出函数说明 避免过多的参数 ...

  2. phpcmsV9手机站内容页有时内容不显示

    phpcmsV9手机站内容页有时内容不显示,修改的办法是: 在文件phpcms\modules\wap\index.php 中 屏蔽第119行,即如下内容 //$content = $contentp ...

  3. 逃跑(escape)

    逃跑(escape) 时间限制: 3 Sec  内存限制: 128 MB 题目描述 输入 第一行是5个正整数,n,m,k,S,T,分别代表无向图点数,边数,蝙蝠的数量,二小姐所在起点的编号,目标点的编 ...

  4. java源码学习(二)Integer

    Integer类包含了一个原始基本类型int.Integer属性中就一个属性,它的类型就是int. 此外,这个类还提供了几个把int转成String和把String转成int的方法,同样也提供了其它跟 ...

  5. Kafka官方文档翻译——实现

    IMPLEMENTATION 1. API Design Producer APIs Producer API封装了底层两个Producer: kafka.producer.SyncProducer ...

  6. JS面向对象一

    面向对象分为三大类 封装,继承,多态! 封装就是在一个函数方法中嵌套另外一个函数方法,外层函数方法返回内层函数方法里面的结果,其中内层函数要调用外层函数定义的局部变量 每个函数方法就是一个局部作用域, ...

  7. RDLC报表纵向合并单元格。

    在做RDLC报表时发现居然没有纵向合并单元格,震惊! 网上查了一些资料,有些方法很可爱,采用去除边框法,但是用这种方法如果要求文本属性居中的话那则达不到美观效果,还有些复杂一点的方法,我都没耐心看,然 ...

  8. 文件存储B+树

    文件存储要选用B+树这样的数据结构 “文件存储要选用B+树这样的数据结构”——没记错的话,这是严蔚敏那本数据结构书上的一句结论.不知道是我没细看还是她没细讲,反正当时纯粹应试地记了这么个结论.不求甚解 ...

  9. Ext & Java 上存图片 Demo

    Ext & Java 上存图片 Demo Ext <html> <head> <script id="microloader" type=&q ...

  10. 静态变量和Session

    静态变量: Application级别的,不同客户端访问同一个变量. Session:对于每个访问的客户端是独立的,都有一个唯一的SessionID.也就是说,不同客户端下,都可以有一个Session ...