JVM GC的垃圾收集器

垃圾收集器



JVM 虚拟机没有提供的垃圾回收规范  所以各种虚拟机提供的垃圾收集器都不一样 这里我们讨论 Sun HotSpot虚拟机1.6版的Update 22 Update22 虚拟机有一以下几种垃圾收集器

1.Serial 收集器
2.ParNew 收集器
3.Parallel Scavenge 收集器
4.Serial Old 收集器
5.Parallel Old 收集器
6.CMS 收集器
7.G1 收集器

Serial 收集器


Serial 收集器在JDK1.3.1之前是虚拟机收集新生代的唯一选择 使用的“标记 — 整理”算法 这个收集器是单线程收集器 他在垃圾回收时必须暂停其他所有工作线程(Stop The World)Serial 收集器的优点:对于单CPU来说 Serial 收集器因为没有线程交互的开销 所以简单且高效

ParNew 收集器



ParNew 收集器是Serial的多线程版本 除了使用多条线程进行垃圾收集以外 还可以使用 Serial 收集器可用的所有参数 收集算法 Stop The World 对象分配规则 回收策略 这些都和 Serial收集器 完全一样ParNew 收集器 除了多线程收集以外没有和 Serial 收集器 有过多的区别 但是 server 模式下的虚拟机首选的新生代收集器 还有一个原因是除了Serial 收集器 和 ParNew 收集器以外 没有其他收集器可以和 CMS 收集器 (Concurrent Mark Sweep)配合在单CPU环境下 Serial 收集器 比 ParNew 收集器 效果更好 甚至由于线程交互的开销 该收集器 通过超线程技术实现两个CPU的环境中都不能百分百超过Serial 收集器 当然随着CPU数量的增加对于GC利用还是有好处的 -XX:ParallelGCThreads 参数可以限制垃圾收集的线程

Parallel Scavenge 收集器

Parallel Scavenge 收集器 也是一个新生代收集器 也是使用复制算法的 并行多线程收集器Parallel Scavenge 收集器 和其他收集器的区别 Parallel Scavenge 收集器 的目标是达到一个可控的吞吐量(Throughput)吞吐量是 CPU用于运行用户的代码于CPU总消耗时间的比值 吞吐量 = 运行用户代码的时间/(运行用户代码时间+垃圾收集时间) 即 虚拟机运行代码的时间是 100分钟 其中垃圾回收花掉了1分钟 那么吞吐量是百分百之九十九停顿时间越短越适合于用户交互的程序 良好的响应速度能提升用户体验;而吞吐量则可以最高效率的利用CPU时间 尽快的完成程序员运算任务 主要适合在后台运算而不需要太多交互的任务Parallel Scavenge 收集器提供了两个参数来控制吞吐量 分别是:最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis直接设置吞吐量大小的 -XX:GCTimeRatioMaxGCPauseMillis 不能为0毫秒 并且 控制GC清理时间如果小于清理垃圾完成所需要的时间 那么垃圾收集器会暂时搁置垃圾清理这样的好处是不会耽误到程序运行时的计算时间但是新生代的内存会因为清理时间不够而需求变高GCTimeRatio 该参数的值只能是大于0小于100的证书 也就是垃圾收集占总时间的比率 相当于吞吐率的倒数 公式 1/(1+n) n为参数的值 比如n=9那么就是1/(1+9) 垃圾收集时间站总时间的10%Parallel Scavenge 收集器 也被称为吞吐量优先收集器 上述收集器还有一个参数-XX:+UseAdaptiveSizePolicy 是一个开关参数当这个参数打开候 不要手工指定新生代大小(-Xmx)、Eden 与 Survivor 区的比例进行监控 动态调整 提供最适合的停顿时间和最大的吞吐率这种调节称之为 GC调节策略(GC Ergonomics)

Serial Old 收集器


Serial Old 收集器 是 Serial收集器 的老年代版也同样是一个单线程收集器使用的“标记 — 整理”算法 这个收集器的主要意义也是被Client模式下的虚拟机使用 如果在Server模式下还有两大用途:

1.JDK1.5以及之前的版本用Parallel Scavenge 收集器搭配使用

2.作为CMS收集器的后备预案在并发收集发生Concurrent Mode Failure 的时候使用Parallel Scavenge 收集器 架构中有PS MarkSweep收集器来进行 老年代 收集 但是PS MarkSweep收集器是以Serial Old 收集器为模板设计的 Serial Old 收集器 和 PS MarkSweep收集器的实现非常接近



Parallel Old 收集器

Parallel Old 收集器 是 Parallel Scavenge 收集器 老年版本使用多线程和“标记 — 整理”算法注重吞吐率和CPU资源敏感的场合都可以优先考虑 Parallel Scavenge 收集器 + Parallel Old 收集器 进行工作

CMS 收集器


CMS 收集器(Concurrent Mark Sweep) 是一种以获取最短回收停顿时间为目标的收集器 因为目前JAVA的应用项目都是B/S架构的服务端上 这类应用尤其注重服务器的响应速度 希望虚拟机垃圾回收停顿时间最短以给用户带来最好的体验 CMS就符合这类应用的

需求
CMS是基于“标记 — 清除”算法实现整个过程分为四个步骤:

1.初始标记 (CMS initial mark)
2.并发标记 (CMS concurrent mark)
3.重新标记 (CMS remark)
4.并发清除 (CMS concurrent sweep)

初始标记、重新标记 这两个步骤仍需要“Stop The World” 初始标记仅仅只是标记一下GC Roors能直接关联到对象 速度很快、并发标记阶段就是进行GC Roots Tracing的过程 而且重新标记阶段则是为了修正并发标记期间因用户变动标记的对象标记记录CMS的优点:并发停顿 Sun的官方文档称之为 并发低停顿收集器(Concurrent Low Pause Collector)
CMS的缺点有三个:

1.CMS对于CPU资源非常敏感

CMS默认启动回收线程数是(CPU数量+3)/4 也就是CPU在4以上时并发回收时收集线程不会超过百分之二十五的CPU资源 但是当CPU不足4时 那么CMS对于用户程序的影响可能就会变得很大 本来运行JAVA项目时CPU负载就比较大还要分出一半去进行收集线程就会导致执行速度突然降低  为了解决这种方法虚拟机提供了一种名为 “增量式并发收集器”(Incremental Concurrent Mark Sweep /i-CMS)的收集器变种  久石让并发标记和并发清理的时候让GC 线程、用户线程交替运行 减少GC线程独占资源的时间 这样整个垃圾回收会更长但是对于用户程序的影响就会少一些 速度下降也没有那么明显 但是目前版本中 i-CMS已经不再提倡用户使用



2.无法处理浮动垃圾(Flaoting Garbage)

CMS处理浮动垃圾可能会出现“Concurrent Mode Failure”失败而导致 Full GC 的产生 首先了解什么是浮动垃圾 由于CMS 并发清理阶段用户线程孩子啊继续运行 伴随程序的运行 自然还会有新的垃圾不断产生 这一部分垃圾出现标记过后CMS 无法在本次收集中继续处理 只好等到下次标记过后在进行清理 这就是浮动垃圾 对应方法是 CMS收集器在老年代使用68%的内存后就激活一个预留空间 (可以通过适当调高参数来提高触发百分比 -XX:CMSInitiatingPccupancyFraction) 一边降低内存回收次数提高性能 如果在CMS运行期间预留内存无法满足程序要求 就会出现一次“Concurrent Mode Failure” 失败 这时 虚拟机将启动后备预案: 临时使用 Serial Old 收集器 来重新进行老年代垃圾收集 -XX:CMSInitiatingPccupancyFraction 参数设置的太高就会早成大量的Concurrent Mode Failure 失败降低性能

3.在收集结束后会有大量空间碎片

因为CMS是基于“标记 — 清除”算法的收集器 这就意味着在收集结束后会产生大量的空间碎片 碎片过多会给大对象的分配带来麻烦 会出现老年代有很大空间剩余但是没有连续空间分配给当前对象 不得不触发一次Full GC 为了解决这个问题 CMS 提供了一个-XX:+UseCMSCompactAtFullCollection开关参数 用于享受完FullGC后给内存一个碎片整理 内存整理无法并发操作所以空间碎片问题没有了但是停顿时间不得不变长 虚拟机还提供了另一种参数 -XX:CMSFullGCsBeforeCompaction 这个参数设置在执行多少次不压缩的Full GC 后带来一次压缩

G1 收集器

G1(Garbage First) 收集器是当前收集器技术发展最前沿的成果在JDK1.6 Update14中提供了Early Access 版本的G1进行使用 
G1收集器的优点:
1.G1收集器是一个基于“标记 - 整理”算法实现的收集器 也就是说他不会产生空间碎片 2.它非常精准的控制停顿 能让使用者明确指定在一个长度为M毫秒的时间片段内 消耗在垃圾手机上的时间不得不超过N毫秒 这已经是实时JAVA(RTSJ)的垃圾收集器的特征了G1收集器可以不牺牲吞吐量的代价完成低停顿的内存回收 这是因为它在极力避免全区域的垃圾收集 之前收集器都是范围都是整个新生代或者老年代 而G1将整个JAVA堆(包括新生代和老年代) 划分为大小固定的独立区域(Region)并且跟踪这些区域里面的垃圾堆积程度 在后台维护一个优先列表 每次根据允许的手机时间 有限收集垃圾最多的区域 这就是 Garbage First 名称的由来
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值