JVM中Hotspot虚拟机中时常被问及的垃圾收集算法和垃圾收集器

垃圾收集算法:即虚拟机垃圾收集的具体过程展示;

垃圾收集器:即使用具体垃圾收集算法来回收内存的具体实现;

【标记--清除算法】是最基础的收集算法,分为两个阶段:首先是标记出所有需要回收的对象,而判定的标准是,是否有引用依然在引用当前对象,即是否可达,然后清除掉所有被标记出来的对象。

该算法的缺点是:效率比较慢,因为java堆中存在有大量对象需要判断是否可达,从而做出标记,比较耗时,另外是清除之后会产生大量不连续的内存碎片,而大量空间碎片可能导致大对象的分配空间不够用,而提前触发一次垃圾回收动作;

针对标记清除算法中空间碎片的问题,

【复制算法】诞生了;它将可用堆空间划分为大小相等的两块,而每次只使用其中一块来分配对象,当内存使用耗光了,即将依然存活的对象复制到另一半未使用的堆空间中,而将已经使用的空间一次性全部清理;其优势在于按顺序分配,空间利用率高,实现简单,但是缺点就不用说了,每次分配只能利用一半的堆空间;而且如果对象一直存活,将会产生大量的复制操作,所以不适用对于老年代的回收,适用于对象存活时间比较短的新生代的回收算法

复制算法虽然提高了内存的利用率但是降低了整个堆空间的使用率,于是乎

【标记-整理算法】,其分为标记和整理两个过程 ,标记过程同标记清理算法,而整理过程是先将存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

【分代收集算法】当前商业虚拟机的垃圾收集都采用分代收集算法;根据对象存活周期的不同将内存划分为几块,一般是把java堆分为新生代和老年代。这样就可以根据各个年代的特点采用最合适的收集算法;

新生代对象都是朝生夕死,能存活的对象比较少,比较适用的算法是复制算法,而老年代对象存活的时间比较久,适合采用【标记-清理】或者【标记-整理】算法;


垃圾收集器:内存回收的具体实现

                            可选收集器

----------------------------------------------------------------------------

新生代 |    Serial   ParNew     Parallel Scavenge     G1

----------------------------------------------------------------------------

老年代:CMS    Serial Old(MSC)  Parallel old       G1

---------------------------------------------------------------------------

下面分别来介绍这几种收集器:

【Serial收集器】最基本,发展历史最悠久的收集器,过去也是新生代收集器的唯一选择,其在垃圾收集时,必须先暂停其他所有的工作线程,直到他收集结束,

可以和Serial收集器配合使用的是SerialOld收集器,新生代GC采用复制算法,并暂停所有用户线程,老年代采用标记-整理算法同样暂停所有用户线程。优势在于单个CPU不存在线程交互,简单高效,适合运行在client模式下;

【ParNew收集器】多线程版本的Serial,多线程并行回收,新生代同样采用复制算法,而老年代采用标记-整理算法;

可以和ParNew收集器一起使用的SerialOld收集器,同样在垃圾回收的时候,也需要暂停所有用户线程,但由于多线程回收垃圾,耗时较短。ParNew是许多运行在Server模式下的虚拟机中首选的新生代收集器,重要原因是因为除了Serial收集器外,目前只有它能与CMS收集器配合使用;在单CPU模式下,其效率绝对没有Serial高

【Parallel Scavenge收集器】也是一个新生代收集器,同样采用的也是复制算法,其目标是控制系统的吞吐量,而吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间);停顿时间越短就越适合需要与用户交互的程序,而高吞吐量则是为了更快速的运算完程序任务,主要适合在后台跑任务。可以通过参数-XX:GCTimeRatio参数和-XX:MaxGCPauseMillis参数来设置其性能,也可以只指定-XX:+UseAdaptiveSizePolicy一个参数来允许系统自己调整最合适的运行性能;

【Serial Old收集器】是Serial收集器的老年版本,它同样也是一个单线程收集器,使用标记-整理算法;这个收集器的主要用于给Client模式下的虚拟机的老年代使用,可以与年轻代的Serial收集器配合使用

【Parallel Old收集器】 是Parallel Scavenge收集器的老年代版本,使用多线程和标记-整理算法,可以和Parallel Scavenge一起工作在注重吞吐量以及CPU时间比较敏感的场合。

【CMS收集器】是一种以获取最短停顿时间为目标的收集器;整个过程分为四个步奏:初始标记,并发标记,重新标记和并发清除,采用的是标记-清除算法,其中初始标记和重新标记让然需要STOP the world;

初始标记仅仅是标记一下GC Roots 能直接关联到的对象,速度很快;

并发标记就是进行GC Roots Tracing的过程;

重新标记阶段是为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,一般用时比初始标记长一点,但是比并发标记要短很多

并发清除阶段就是清除被标记为无用的对象,回收内存;

整个过程中用时最长的并发标记和并发清除,都是和用户线程一起工作的,所以总体上来说,CMS内存回收过程是与用户线程一起并发执行的。

其优点在于并发收集,低停顿。

缺点在于:对CPU资源敏感,无法处理浮动垃圾(标记过后产生的垃圾,只能等下次收集),最后一个缺点就是标记清理产生的内存碎片。


最后的收集器,也是比较新的收集器为【G1收集器】,是一款面向服务端应用的垃圾收集器。

特点如下:

1)并行与并发;

2)分代收集

3)空间整合,从总体来看是采用标记-整理算法,而从局部来看是复制实现的。

4)可预测的停顿,跟踪各个Region里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region.

G1采用模块式回收垃圾机制提高回收效率,而避免全表扫描的策略是维护Remembered Set,即每个区域都有一个与之对应的Remembered Set.,记录其他区域中被引用的对象

若果不计算对Remembered Set维护的操作,G1的回收步奏为:

1)初始标记

2)并发标记

3)最终标记

4)筛选回收


内存分配策略:

对象优先分配在Eden

大对象直接进入老年代

长期存活的对象将进入老年代

空间分配担保等


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值