您的位置:首页 > 编程语言 > Java开发

读 - 深入理解java虚拟机 - 笔记(六-3) - 垃圾收集器和内存分配策略(3章)-垃圾收集器

2017-12-01 17:11 465 查看
有关垃圾收集器的文章,我纯粹也是翻译,因为自己没有这方面经验,说实话,做项目到今天,都没有遇到垃圾回收的问题,因为自身从事的项目数据量不大,难以接触这种问题,手动模拟呢,又不会有真正的问题现场那么令人欢欣,

大致上现在有的收集器一般如下图:


针对每个收集器我先做个简单的归类统计:



这里对于并行和并发的就不去做过多解释了。

1.Serial收集器

最基本,最稳定高效的垃圾收集器。Client模式下的默认新生代垃圾收集器。



2.Serial old收集器

是Serial 的老年代垃圾收集器。

Client模式下是老年代的默认收集器。

Server模式下在jdk1.5之后与Parallel Scavenge垃圾收集器搭配使用,另一种作为CMS的备用方案,在CMS发生Concurrent Mode Failure时使用。

3.ParNew收集器

ParNew收集器是Serial的多线程版本。

server模式下的新生代垃圾收集器,现在只有它能和CMS配合使用,



4.Parallel Scavenge收集器

新生代,并行,复制算法垃圾收集器。它的目标是达到一个可控的吞吐量。

吞吐量= 运行用户代码时间 / (运行用于代码时间+垃圾回收时间),虚拟机总共运行100分钟,垃圾回收花掉1分钟,吞吐量是99%。

它是一个吞吐量优先的收集器,会根据当期西永的运行情况收集性能监控信息,动态调整这些参数已提供最合适的停顿时间或者最大吞吐量。

5.Parallel Old收集器

Parallel Scavenge的老年代版本,与Parallel Scavenge形成配合,注重吞吐量。



6.CMS收集器

6.1目标和思想:

追求的是最短的停顿时间,基于标记-清除算法。

6.2过程

1. 初始标记 

需要“Stop the World”初始标记只是标记一些GC Roots能关联到的对象,对于发现这个关联对象,虚拟机是做过优化的,后面再讨论,是有专门的东西来记录对象的分配以及它所属的关联,因此这一阶段时间其实很少。

2.并发标记

随着用户线程一起并发执行,进行GC RootsTracing的过程。

3.重新标记

为了修正并发标记期间因为用户程序继续运行导致标记产生变化的那一份部分对象的标记记录,停顿时间会比初始标记阶段稍微长一点,远比并发标记时间短。

4.并发清除

垃圾清理工作



6.3优点

并发收集,低停顿。

6.4缺点

1. CPU资源敏感,默认启动 (CPU数量+3)/4的线程进行垃圾回收,影响程序应用和吞吐量。

2. 浮动垃圾,请清理阶段,由于是并发的,那么在这个阶段产生的垃圾由于没有被标记,因此不会被清理掉,于是产生了“浮动垃圾”,只能是在下一次的GC时再清理。而由于此时用户线程任然在运行,因此还需要预先留出一部分内存给此时产生的对象。

JDK1.5时,默认设置了当年老代使用了68%的空间时触发CMS收集。

JDK1.6时。默认设置了92%,如果在CMS运行期间预留出的空间无法满足程序需要,就会出现“Concurrent Mode Failure”,这就是上面说的备案,Serial Old启动,重新进行一次Full GC,需要停顿更长的时间。

百分比设置:-XX:CMSInitiatingOccupancyFraction

3.碎片化问题,因为采用的是标记-清除算法,因此即使说年老代回收了大部分内存,但是不足以满足一个大对象的分配,又触发了一次Full GC。默认参数设置

-XX:+UseCMSCompactAtFullCollection,默认开启,进行合并整理。

G1

G1是最新的垃圾收集器,但是从sun发表论文的2004年开始,一直到现在才投入商用,其实是很复杂的,因此我也不奢求能对其知道有多少,了解下吧。

1.并发与并行

G1能充分利用多CPU和多核的硬件优势来缩短停顿时间,能够使用并发的方式是的java程序继续执行。

2.分代收集

G1的分代理念和其他不同,它管理的是整个GC堆,采用不同的方式去处理新创建的对象和已经存活并且熬过多次GC的旧对象

3.空间整合

与CMS不同,G1从整体上是采用标记整理算法实现的,从局部(两个Reginon)来看,这边的局部是G1收集器里面的一个概念,下面会介绍,是基于复制算法的,意味着不会产生内存碎片的问题。

4.可预测的暂停

建立了一个停顿时间的模型,能提供指定一个长度为M毫秒的时间片段内,垃圾回收的时间不超过N毫秒。

5.垃圾收集范围

以上垃圾回收器的收集范围是新生代或者老年代,G1不再如此,使用G1时,java堆的内存布局差别很大,分成了多个大小相等的独立区域(Region),基于此,G1才能建立可预测的停顿时间模型,G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需的时间大小),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。

6.运作步骤

6.1初始标记

仅仅标记GC Roots能直接关联的对象并且修改TAMS的值,这个TAMS是什么,不清楚,它的作用是让下一阶段用户程序并发运行时,能在正确可用的Region中农创建新对象,这个阶段需要停顿线程,耗时短。

6.2并发标记

从GC Roots开始进行可达性分析,找出存活对象,耗时少,可并发运行。

6.3最终标记

为了修正在并发标记阶段,用户程序继续运作从而导致标记产生变动的那一部分对象的标记记录,虚拟机将这段时间变化记录在线程的Remembered Set中。

6.4删选回收

对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间制定回收计划。



文末再次强调,这只是书本的知识记录,并没有新的东西和个人观点在其中,因为本人工作日常中根本接触不到虚拟机的bug,只能说遗憾了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐