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. Spring Security3详细配置

    Spring Security3详细配置 表名:RESOURCE 解释:资源表备注: 资源表 RESOURCE(资源表) 是否主键 字段名 字段描述 数据类型 长度 可空 约束 缺省值 备注 是 ID ...

  2. 处理jQuery append加入的元素 绑定事件无效的方法

    通过jquery append(或者before.after,一样)新添加进网页的元素,常用的事件不能触发,比如:append了id 为 abc 的元素,那么 $(#abc).click(functi ...

  3. UWP的Converter妙用

    MVVM模式的使用,简化了UWP应用的开发,使层次更加分明.在写xaml的时候,有些小技术还是很实用的:比如Converter,字面上理解是转换器,那它到底是转换什么的?接触过的可能知道它起的是类型转 ...

  4. JavaScript练习笔记整理·2 - 6.24

      Codewars地址:https://www.codewars.com/ 欢迎和大家一起来讨论~   基础练习(1):   我的解答为: function isIsogram(str){ if(s ...

  5. python+NLTK 自然语言学习处理:环境搭建

    首先在http://nltk.org/install.html去下载相关的程序.需要用到的有python,numpy,pandas, matplotlib. 当安装好所有的程序之后运行nltk.dow ...

  6. 实现自己的.NET Core配置Provider之EF

    <10分钟就能学会.NET Core配置>里详细介绍了.NET Core配置的用法,另外我还开源了自定义的配置Provider:EF配置Provider和Yaml配置Provider.本文 ...

  7. JavaScript函数部分

    函数部分学习:+parseInt(): -parseInt()函数将其收到的任何输入值(通常是字符串)转换成整数类型输出,如果转换失败就返回NaN. -parseInt(“参数”,第二参数基数):没有 ...

  8. java对mysql的增删改查

    -----连接数据库 package connectdb;import java.sql.*;class Dbcon { // 此处连接数据库,独立开一个类,以后操作数据库的每次连接就不用写这么多 p ...

  9. Ext TabPanel tabbar添加按钮

    tabPanel tabbar添加按钮 this.tabPanel = Ext.create('Ext.tab.Panel', { tabBar:{ items:[{ //组件靠右 xtype: 't ...

  10. h5可预览 图片ajax上传 (补更),后台数据获取方法---php

    原理是 先获取,然后手动转移文件路径,不然会被服务器自动删除 demo如下: <?php header('content-Type:text/html;charset=utf-8'); $fil ...