Java垃圾回收精粹 — Part1
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设定目标:
- 吞吐量:花费在垃圾收集上的时间占整个应用程序工作量的比例。通过“-XX: GCTimeRatio = 99;”来设置目标吞吐量;默认值是99,这意味着有1%的时间用于垃圾收集。
- 延迟:由于垃圾回收引起的响应暂停的时间。设置GC暂停的延迟使用“- XX :MaxGCPauseMillis =< n>”。
- 内存:我们的系统内存通常用来存储状态,在管理时经常要进行复制和移动。在任何时间点,被应用程序保留的活动对象集被称为存活集。“- 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的更多相关文章
- Java垃圾回收精粹 — Part4
Java垃圾回收精粹分4个部分,本篇是第4部分.在第4部分里介绍了G1收集器.其他并发收集器以及垃圾收集监控和调优. Garbage First (G1) 收集器 G1 (-XX:+UseG1GC)收 ...
- Java垃圾回收精粹 — Part3
Java垃圾回收精粹分4个部分,本篇是第3部分.在第3部分里介绍了串行收集器.并行收集器以及并发标记清理收集器(CMS). 串行收集器(Serial Collector) 串行收集器是最简单的收集器, ...
- Java垃圾回收精粹 — Part2
Java垃圾回收精粹分4个部分,本篇是第2部分.在第2部分里介绍了Hotspot中的堆结构.对象分配以及次要回收. Hotspot中的堆结构 理解不同的收集器的工作方式,是探讨Java堆结构如何支持分 ...
- 【转载】Java垃圾回收机制
原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...
- 【转】深入理解 Java 垃圾回收机制
深入理解 Java 垃圾回收机制 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- 深入理解java垃圾回收机制
深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...
- Java GC系列(2):Java垃圾回收是如何工作的?
本文由 ImportNew - 伍翀 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 本教程是为了理解基本的Java垃圾回收以及它是如何 ...
- Java GC系列(1):Java垃圾回收简介
本文由 ImportNew - 好好先生 翻译自 javapapers. Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Ja ...
- Java垃圾回收介绍(译)
在Java中,对象内存空间的分配与回收是由JVM中的垃圾回收进程自动完成的.与C语言不同的是,在Java中开发者不需要专门为垃圾回收写代码.这是使Java流行的众多特征之一,也帮助了程序员写出了更好的 ...
随机推荐
- 完全禁用Wordpress的升级功能
wordpress自己带有一个自动升级的功能,也就是说,如果wp检测到官方已经有新的升级可用的话他就会自己升级上去.这可能对于某些场合是个不错的功能,但是对于一些已经对系统大量魔改或者对插件稳定性不抱 ...
- 5 Linux网络编程基础API
5.1 socket地址API 大端字节序(网络序):高位在低址,低位在高址 小端字节序(主机序):低位在低址,高位在高址 判断,利用联合的特性: #include <iostream> ...
- BNUOJ 52516 Just A String
$KMP$. 枚举每一个后缀,去原串中进行匹配,每次匹配到原串到$i$位置的后缀与这次枚举的后缀的前缀,更新答案. #include<bits/stdc++.h> using namesp ...
- Sublime Text3 配置Python3编译环境
Sublime Text3 配置Python编译环境 进入Sublime Text3 ,然后选择菜单:工具(T)==>编译系统(U)==>新编译系统... 把上面的代码换成如下代码: &q ...
- SSM相关资料
MyBatis: 官方文档 MyBatis-Spring:官方文档 SpringMVC整合MyBatis实例 SSM框架详细整合教程 一步一步带你搭建后台管理系统之SSM框架整合 SSM框架入门和搭建 ...
- 【拓扑排序或差分约束】Guess UVALive - 4255
题目链接:https://cn.vjudge.net/contest/209473#problem/B 题目大意:对于n个数字,给出sum[j]-sum[i](sum表示前缀和)的符号(正负零),求一 ...
- Jenkins多选项框使用
多选框的使用场景还是挺多的,比如发布多个服务,或者选择哪些服务器 想要使用多选项,则需要安装插件extend choice parameter,然后在项目中配置参数化构建过程 配置完上面,我们就可以在 ...
- Selenium模拟登陆简书
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.c ...
- 「ZJOI2018」历史
「ZJOI2018」历史 前置知识 \(\text{LCT}\) 维护子树信息,考虑辅助树上一个节点的子树信息只是其代表的这一段链的信息,设 \(S(u)\) 为节点 \(u\) 的子树信息,那么在辅 ...
- CodeForces - 1016C Vasya And The Mushrooms
题面在这里! 好久没有体会这种A题的快感了23333 一开始看错了,以为权值是从1开始的,不过这样不要紧,最后把算的答案减去两行数的和就是正确的答案了. 然后发现位于一个角上的时候,我们其实只有两种选 ...