Java垃圾回收精粹分4个部分,本篇是第1部分。在第1部分里介绍了权衡点、对象生命周期以及全局暂停事件。

串行、并行、并发、CMS、G1、年轻代(Young Gen)、新生代(New Gen)、旧生代(Old Gen)、持久代(Perm Gen)、伊甸区(Eden)、年老区(Tenured)、幸存区(Survivor Spaces)、安全点(Safepoints)以及数百种JVM启动参数。当你试图调整垃圾回收器使你的Java应用程序获得需要的吞吐量和延迟时,这些会难倒你吗?如果回答是,你也不必担心,这样的人还有很多。文档中对垃圾收集的描述感觉就像飞机操作手册一样复杂,每个旋钮和转盘足够详尽细致,但就是搞不清如何飞起来。本文将试图解释在为特定工作负载选择和调整垃圾收集算法时需要了解的权衡点。

本文将重点关注甲骨文的HotSpot JVM和OpenJDK,这俩是最常见的。最后也会讨论其他商业JVM作为替代方案。

权衡点(The Tradeoffs)

民间有句俗话叫:“舍不得孩子套不着狼”。若我们想得到些东西,我们通常必须放弃另一些东西。当这句话用在垃圾回收上,主要通过三个变量为GC设定目标:

  1. 吞吐量:花费在垃圾收集上的时间占整个应用程序工作量的比例。通过“-XX: GCTimeRatio = 99;”来设置目标吞吐量;默认值是99,这意味着有1%的时间用于垃圾收集。
  2. 延迟:由于垃圾回收引起的响应暂停的时间。设置GC暂停的延迟使用“- XX :MaxGCPauseMillis =< n>”。
  3. 内存:我们的系统内存通常用来存储状态,在管理时经常要进行复制和移动。在任何时间点,被应用程序保留的活动对象集被称为存活集。“- Xmx<n>”用来设置最大堆大小,可以用来调节应用程序可用的堆大小。

注意:通常HotSpot不能达到这些指标,而且会没有任何警告默默地继续运行,与设定的参数值愈行愈远。

延迟散布在整个垃圾回收过程中。它会以稍稍加一些平均延迟时间为代价,减少在最坏情况下的延迟或者使延迟不会过于频繁地出现,让我们可以接受。我们不要把术语“实时”理解为尽可能小的延迟,而应当看做无论吞吐量如何都保证有一个明确的短暂延迟。

当然,对于有些程序的工作负载吞吐量是最重要的。譬如,一个长时间运行的批处理作业;如果一个批处理作业为了垃圾收集而偶尔停顿几秒,只要整体上可以更快完成那就没问题。

实际上所有其他工作负载,从人机交互的应用程序到金融交易系统,如果系统出现没有响应超过几秒钟,在某些情况下甚至是几毫秒,那麻烦就大了。在金融交易系统中牺牲吞吐量换延迟常常是值得的。当然也有可能是,应用程序被可用的物理内存数限制住却又必须保持运行,在这种情况下,我们不得不放弃对延迟和吞吐量方面的性能追求。

权衡结果通常是这样的:

  • 在很大程度上,可以使用内存消耗更多的垃圾收集算法减少垃圾收集的平均占用时间。
  • 可预见的最坏情况是延迟引发的停止响应。可以通过限制活动集(live set)和维持较小的堆来减少这种情况。
  • 可以通过管理堆和代大小,以及控制应用程序的对象分配率来减少暂停发生的频率。
  • 较长的暂停的发生频率可以通过并行运行GC和应用程序来减少,但有时会影响吞吐量。

对象生命周期

垃圾收集算法的优化通常假设大多数对象都存活了一个很短的周期,只有少部分存活时间很长。在大多数应用程序里,多数对象有一个明确的生命周期,仅有很小的一部分对象会贯穿运行整个过程。在垃圾收集理论中,这种现象通常被称为“infant mortality”(婴儿死亡率) 或 “weak generational hypothesis”(弱代假设)。譬如,循环迭代器大多生命周期极短,而静态字符串则在整个程序生命周期中都有效。

实验表明,分代垃圾收集器常常比不分代有一个数量级的提升,因而在几乎所有的服务器JVM中都使用分代垃圾回收。通过为对象分代我们知道,一块新分配对象的区域里存活对象往往非常少。因此,使用一个收集器清理这些新生的少数存活对象,并将它们拷贝到另一个年老代的区域里会很奏效。Hotspot垃圾回收器使用在GC周期中幸存的次数作为一个对象的年纪。

注意:如果你的应用程序不断产生大量对象并且存活很久,显而易见你的应用程序将要花上不少时间在垃圾回收上。同样昭然若揭的是,你会花不少时间来调优Hotspot的垃圾回收器。这种情况下,代“过滤器”不太有效。它会频繁地收集长时生存代而花费了颇多时间,最终导致了GC效率低下。年老代又那么分散,所以年老代的收集算法效率更低。分代垃圾收集器往往在两个不同回收周期操作:收集完短时间存活对象之后的次要回收(Minor collections);以及较低频率的主要回收(Major collections),即在对旧生代区域进行回收之后。

全局暂停事件(stop-the-world events)

在垃圾回收过程中的程序暂停被称之为“全局暂停事件”。在实际工程中为了进行内存管理,垃圾回收器必须定期这样做。根据不同的算法,不同的收集器会在不同的时间、不同的地方暂停整个程序。为了完全停止程序,你必须暂停所有运行中的线程。“安全点”是指在程序执行中到达的某个点,此时GC根对象全都是已知的,并且所有的堆对象的内容是一致的。当运行到 “安全点”的时候,垃圾回收器会发送一个信号让线程暂停。根据线程正在做的事情,可能需要花费一些时间才能到达“安全点”。“安全点”的检查通常是在函数的返回或者循环边界结束,但是可以进行优化使其更加动态。比如:某线程正在复制一个大数组,克隆一个大的对象,或者执行一个有限次的计数循环,这可能需要几毫秒才能到达一个“安全点”。 “安全点抵达时间”(TTSP)对于低延迟的应用非常重要。除了其他的GC标志之外,启用“XX:+PrintGCApplicationStoppedTime ”标志可以输出这个时间。

注意:对于有大量并行线程的应用程序来说,当全局暂停发生时,系统将会发生明显的调度压力并在结束后恢复。因此依赖全局暂停(stop-the-world)较少的算法会更有效率。

Java垃圾回收精粹 — Part1的更多相关文章

  1. Java垃圾回收精粹 — Part4

    Java垃圾回收精粹分4个部分,本篇是第4部分.在第4部分里介绍了G1收集器.其他并发收集器以及垃圾收集监控和调优. Garbage First (G1) 收集器 G1 (-XX:+UseG1GC)收 ...

  2. Java垃圾回收精粹 — Part3

    Java垃圾回收精粹分4个部分,本篇是第3部分.在第3部分里介绍了串行收集器.并行收集器以及并发标记清理收集器(CMS). 串行收集器(Serial Collector) 串行收集器是最简单的收集器, ...

  3. Java垃圾回收精粹 — Part2

    Java垃圾回收精粹分4个部分,本篇是第2部分.在第2部分里介绍了Hotspot中的堆结构.对象分配以及次要回收. Hotspot中的堆结构 理解不同的收集器的工作方式,是探讨Java堆结构如何支持分 ...

  4. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

  5. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  6. 深入理解java垃圾回收机制

    深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  7. Java GC系列(2):Java垃圾回收是如何工作的?

    本文由 ImportNew - 伍翀 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 本教程是为了理解基本的Java垃圾回收以及它是如何 ...

  8. Java GC系列(1):Java垃圾回收简介

    本文由 ImportNew - 好好先生 翻译自 javapapers. Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Ja ...

  9. Java垃圾回收介绍(译)

    在Java中,对象内存空间的分配与回收是由JVM中的垃圾回收进程自动完成的.与C语言不同的是,在Java中开发者不需要专门为垃圾回收写代码.这是使Java流行的众多特征之一,也帮助了程序员写出了更好的 ...

随机推荐

  1. python 爬图

    利用bs库进行爬取,在下载html时,使用代理user_agent来下载,并且下载次数是2次,当第一次下载失败后,并且http状态码是500-600之间,然后会重新下载一次 soup = Beauti ...

  2. interesting Integers(数学暴力||数论扩展欧几里得)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwwAAAHwCAIAAACE0n9nAAAgAElEQVR4nOydfUBT1f/Hbw9202m0r8

  3. EF – 6.一对一关联

    5.6.6 <一对一关联概述>  5.6.7 <一对一关联CRUD演示>  在两讲视频中,首先介绍了数据库中一对一关联表的设计规范,接着通过实例介绍了如何合适Entity Fr ...

  4. WordPress SMTP发送邮件插件:WP SMTP

    对于一个网站而言,发送邮件的功能是必不可少的,现在的主机一般都支持发送邮件,但是不同的主机由于函数限制或者某些其他原因,可能造成没办法正常发送邮件.这时候,我们可能就要借助第三方SMTP发送邮件. 对 ...

  5. Oracle与MySQL连接配置

    MySQL: Driver: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/GBDSPT(数据库名称) Oracle: Driver:o ...

  6. ImportError: No module named yum

    [root@localhost]# yum-complete-transactionTraceback (most recent call last):  File "/usr/sbin/y ...

  7. ACID数据库事务正确执行的四个基本要素的缩写

    ACID,指数据库事务正确执行的四个基本要素的缩写.包含:原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability).一个支持事务(T ...

  8. vue-router在IE11中页面不跳转

    情景: IE11浏览器中,在进行正常页面跳转操作后(页面A跳转到页面B),点击浏览器的左上角的‘后退’按钮,点击后,可以看到url地址已经发生了变化(url由页面B变为页面A),hash值也已经是上一 ...

  9. 【算法与数据结构实战】线性表操作-实现A并B,结果放入A中

    //数据结构与算法基础题1:线性表操作,实现A并B,结果放入A中 #include "stdafx.h" #include <iostream> #include &l ...

  10. 洛谷——P1330 封锁阳光大学

    P1330 封锁阳光大学 题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构 ...