设为首页 加入收藏

TOP

Java垃圾收集机制(二)
2017-04-07 10:25:06 】 浏览:353
Tags:Java 垃圾 收集 机制
在CPU数量较少时,CMS对用户程序的影响可能更大。


2.CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”而导致一次Full GC的产生。由于并发清理阶段用户线程还在运行,因此就会有新的垃圾产生,且CMS无法在当次收集中处理掉,需要留到下一次GC时再清理。这部分垃圾就是浮动垃圾。正是由于并发清理阶段用户线程还在执行,那也就是需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其它收集器一样等到老年代几乎完全被填满才进行收集,需要预留一部分空间提供并发收集时的程序运作使用。如果CMS运行期间预留内存无法满足需要会出现“Concurrent Mode Failure”失败,从而触发Serial Old收集器进行垃圾回收。


3.CMS是一款基于标记-清除算法的回收器,因此会产生内存碎片。为解决内存碎片问题,CMS提供了一个-XX:+UseCMSCompactAtFullCollection开关参数,用于在CMS收集器要进行FullGC时开启内存碎片的合并整理过程,内存整理过程是无法并发的,因此停顿时间会变长。因此虚拟机设计者还提出了-XX:CMSFullGCsBeforeCompaction参数,这个参数用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)。


 G1(Garbage-First)收集器是一款面向服务端应用的垃圾收集器,与其他GC收集器相比,G1具备以下特点:


1.并行与并发:G1充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短停顿时间,部分其它收集器原本需要停顿Java线程执行GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。


2.分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。它能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的旧对象以获取更好的收集效果。


3.空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。


4.可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。


  其它收集器收集的范围是新生代或老年代,而使用G1收集器时,Java堆内存布局与其他收集器有很大差别,它将Java对划分成多个大小相等的独立区域,虽保留了新生代和老年代的概念,但新生代和老年代不再是物理隔离的,它们都是一部分Region的集合。


  G1收集器之所以能够建立可预测的停顿时间模型,是因为它可以有计划的避免对整个堆中进行垃圾回收。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所需要的空间大小以及回收所需要时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region,从而提高了在有限时间内获取尽可能高的收集效率。


  G1是把内存“化整为零”,但是各个Region并不是不相关的,因此在某个Region上进行垃圾回收时,对对象做可达性判定确定对象是否存活时,难道还需要扫描整个Java堆才能保证正确性吗?其实不然,在G1收集器中,Region之间的对象引用,虚拟机使用Remembered Set来避免对全堆的扫描。每个Region都有一个Remembered Set,虚拟机发现程序在对Reference类型的数据进行写操作时,都会产生一个Write Barrier暂时中断写操作,检查Reference引用的对象是否处于不同的Region中,如果是,便通过CardTable把相关的引用信息记录到被引用对象所属的Region的Remembered Set中。当进行内存回收时,在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏。


  如果不计算维护Remembered Set的操作,G1收集器的运作大致分为4个步骤:初始标记、并发标记、最终标记、筛选回收。初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短。并发标记阶段是从GC Roots开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行。而最终标记阶段则是则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面。最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行。最后在筛选回收阶段首先对各Region的回收价值和成本进行排序。根据用户所期望的GC停顿时间来制定回收计划。



首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java并发编程ThreadLocal 详解 下一篇Java内存分配与回收策略

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目