Java垃圾回收精粹 — Part3
Java垃圾回收精粹分4个部分,本篇是第3部分。在第3部分里介绍了串行收集器、并行收集器以及并发标记清理收集器(CMS)。
串行收集器(Serial Collector)
串行收集器是最简单的收集器,对于单处理器系统真是绝佳上选。当然,它也是所有收集器里面最不常用的。串行收集器使用一个单独的线程进行收集,不管是次要收集还是主要收集。在年老区中分配的对象使用一个简单的凹凸指针算法(bump-the-pointer algorithm)即可。当tenured space填满后会触发主要回收。
译注:按照这种技术,JVM内部维护一个allocatedTail指针,始终指向先前已分配对象的尾部。当新的对象分配请求到来时,只需检查代中剩余空间,即从allocatedTail到代尾geneTail是否足以容纳该对象,并在“满足”的情况下更新allocatedTail指针和初始化对象。
并行收集器(Parallel Collector)
并行收集器有两种形式:一种并行收集器(-XX:+ UseParallelGC)在次要回收中使用多线程来执行,在主要回收中使用单线程执行;另一种是从Java 7u4开始默认使用的并行旧生代收集器(Parallel Old collector )(XX:+UseParallelOldGC),在次要回收和主要回收均使用多线程。在tenured space分配的对象使用简单的凹凸指针(bump-the-pointer)算法即可。当年老区填满后会触发主要回收。
在多处理器系统上,并行旧生代收集器是吞吐量最大的收集器,只有收集开始时才会影响到正在运行的程序。然后使用最高效算法、多个并行线程进行收集。这使得并行旧生代收集器非常适合批处理应用。
回收年老代的成本受存留对象数量影响较大,受堆大小影响较小。要提高并行旧生代收集器的搜集效率、提供更大的吞吐量,需要更大的内存、更长的回收时间、更少的收集时暂停。
这被期望成为最快的次要回收。因为在这个收集器里,到年老区的晋升是一个简单的凹凸指针(bump-the-pointer)和复制操作。
对于服务器应用程序来说,并行旧生代收集器必须是垃圾收集的第一站。如果主要回收的暂停超过了应用程序的容忍下限,需要考虑使用与应用程序并发执行的收集器来收集年老对象。
注意:在现在的硬件条件下,对年老代的压缩每GB的存活对象预计需要暂停一到五秒。
注意:在多插槽的CPU的服务器应用程序中设置“-XX:+ UseNUMA”,可以通过并行收集器能获得更好的性能。这是因为是在线程本地的CPU插槽上分配给Eden内存。遗憾的是其他收集器不支持这个功能。
CMS(并发标记清理收集器,Concurrent Mark Sweep)
CMS(-XX:+ UseConcMarkSweepGC)收集器在年老代中使用,专门收集那些在主要回收中不可能到达的年老对象。它与应用程序并发运行,在年老代中保持一直有足够的空间以保证不会发生年轻代晋升失败。
晋升失败将会触发一次FullGC,CMS会按照下面几个步骤处理:
- 初始化标记:寻找GC根。
- 并发标记:标记所有从GC根开始可到达的对象。
- 并发预清理:检查被更新过的对象引用和在并发标记阶段晋升的对象。
- 重标记:捕捉预清洁阶段开始更新的对象引用。
- 并发清理:通过回收被死对象占用的内存更新可用空间列表。
- 并发重置:重置数据结构为下一次运行做准备。
当年老对象变得不可访问时,占用空间会被CMS回收并且放入到空闲空间列表中。当晋升发生的时候,会查询空闲空间列表,为晋升对象找到大小合适的位置。这增加了晋升的成本,因而相比并行收集器也增加了次要收集的成本。
注意:CMS 不像压缩收集器,随着时间的推移会在年老代中产生碎片。对象晋升可能失败,因为一个大对象可能在年老代在找不到一块足够容身的可用空间。如果发生了这样的事,日志会记录一条“晋升失败”的消息,然后并且触发一次FullGC来压缩存活的年老对象。对于这种压缩驱动的FullGC,由于CMS使用单线程压缩,可以想见会比使用并行旧生代收集器的主要回收使用更长的暂停时间。
CMS尽可能的与应用程序并发运行,这里面有几层含义。首先,CPU的时间会被收集器占用,因此CPU可用于应用程序的时间片减少。CMS消耗的时间量与到tenured space(老年区)的对象晋升量呈线性正相关。其次,对于并发GC周期中的某些阶段,所有的应用线程必须到达一个安全点,比如标记GC根并执行并行的重标记来检查更新。
注意:如果一个应用程序年老区的对象发生非常明显的变化,重新标记阶段将非常耗时,在极端情况下,它可能比一个完整的并行旧生代收集器的压缩时间还要长。
CMS要想降低FullGC的频率,可以通过降低吞吐量、使用更耗时的次要回收以及占用更大的空间的方式实现。 根据不同的晋升率,吞吐量会比并行收集少10%-40%。CMS同样要求多于20%的空间来存放额外的数据结构和“漂浮垃圾(floating garbage)”,漂浮垃圾是在并发标记阶段丢掉的,扔给下一个收集周期处理的对象。
高晋升率以及由此产生的碎片,有时候可以通过增加新生代和年老代空间的大小来减少。
注意:当CMS回收的空间不能满足晋升需求的时候,它可能遇到“并发模式失败(concurrent mode failures)”,在日志中可以找到记录。产生这种情况可能是因为是收集得太迟,这样可以通过调整策略来解决。也可能是收集的空间空闲率跟不上高的晋升率或则某些应用超高的对象更新率。如果你程序的晋升率和更新率太高,你可能需要改变你的应用程序来减少晋升的压力。给CMS加大内存有时候会使情况更糟,因为这需要扫描更多的内存。
Java垃圾回收精粹 — Part3的更多相关文章
- Java垃圾回收精粹 — Part4
Java垃圾回收精粹分4个部分,本篇是第4部分.在第4部分里介绍了G1收集器.其他并发收集器以及垃圾收集监控和调优. Garbage First (G1) 收集器 G1 (-XX:+UseG1GC)收 ...
- Java垃圾回收精粹 — Part2
Java垃圾回收精粹分4个部分,本篇是第2部分.在第2部分里介绍了Hotspot中的堆结构.对象分配以及次要回收. Hotspot中的堆结构 理解不同的收集器的工作方式,是探讨Java堆结构如何支持分 ...
- Java垃圾回收精粹 — Part1
Java垃圾回收精粹分4个部分,本篇是第1部分.在第1部分里介绍了权衡点.对象生命周期以及全局暂停事件. 串行.并行.并发.CMS.G1.年轻代(Young Gen).新生代(New Gen).旧生代 ...
- 【转载】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流行的众多特征之一,也帮助了程序员写出了更好的 ...
随机推荐
- HDU 3085 Nightmare Ⅱ(双向BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085 题目大意:给你一张n*m地图上,上面有有 ‘. ’:路 ‘X':墙 ’Z':鬼,每秒移动2步,可 ...
- Python+Selenium 自动化实现实例-数据驱动实例
#coding=utf-8 from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) ...
- [ JS 进阶 ] Repaint 、Reflow 的基本认识和优化
你是不是经常听师兄或一些前端前辈说不能用CSS通配符 *,CSS选择器层叠不能超过三层,CSS尽量使用类选择器,书写HTML少使用table,结构要尽量简单-DOM树要小....等这些忠告,以前我就大 ...
- centos修改oracle字符集
1.首先以sysdba的身份登录上去 conn /as sysdba2.关闭数据库shutdown immediate;3.以mount打来数据库,startup mount4.设置session S ...
- lr_get_transaction_duration 函数介绍
lr_get_transaction_duration 用于获取事务所消耗的时间. 实例: Action() { double trans_time; //定义变量 web_url("www ...
- 9 行 javascript 代码获取 QQ 群成员
昨天看到一条微博:「22 行 JavaScript 代码实现 QQ 群成员提取器」. 本着好奇心点击进去,发现没有达到效果,一是 QQ 版本升级了,二是博客里面的代码也有些繁琐. 于是自己试着写了一个 ...
- linux网络管理----网络命令
1 Linux网络命令之网络环境查看命令 ifconfig 2 Linux网络命令之网络测试命令 telnet 基本已经被ssh替代了,telnet是明文传递,不安全
- python解决组合问题
1.问题描述 比如9个数中取4个数的组合以及列出各种组合,该如何做? 我们可以考虑以下一个简单组合:从1,2,3,4,5,6中,如何选取任意四个数的组合. 固定:1 2 3 ,组合有1234 ...
- codevs 1214 线段覆盖
1214 线段覆盖 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给定x轴上的N(0<N<100)条线段,每个线段 ...
- NOIP2017 D2T3列队
这题我改了三天,考场上部分分暴力拿了50,考完试发现与正解很接近只是没写出来. 对于每一行和最后一列建n+1颗线段树,维护前缀和. 复杂度qlogn 假如你移动一个坐标为(x,y)的人,你要将第x行线 ...