堆内存常见的分配策略、 经典的垃圾收集器、CMS与G1收集器及二者的比较,
堆内存常见的分配策略、 经典的垃圾收集器、CMS与G1收集器及二者的比较,
堆内存常见的分配策略
针对的是Serial 加 Serial Old 客户端默认收集器组合下的内存分配和回收策略
经典的垃圾收集器
CMS 收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的垃圾收集器。从名字可以看出,CMS 是基于标记-清除算法的。它的运作过程主要分为四个步骤:
CMS 的缺点:
- CMS收集器对处理器资源敏感。在并发阶段,虽然不会导致用户停顿(STW),但会占用一部分线程(计算机资源)导致应用程序变慢,吞吐量降低。CMS默认开启回收线程数是 (处理器核心数量 + 3)/4。当处理器核心数量大于4个时,垃圾回收线程只占不超过 25%的处理器资源,且随着处理器核心数量增加而降低。但处理器核心数量不足4个时,会严重影响用户程序。为了缓解这个问题,虚拟机提供了增量式并发收集器的CMS变种,在并发标记和并发清理过程中,垃圾收集线程和用户线程交替运行,但效果一般,已标记为废弃。
- 无法处理“浮动垃圾”,有可能出现 Concurrent Mode Failure失败,导致进一步 STW 的Full GC。在并发标记和并发清理过程中,用户线程还在运行,自然还会伴随新的垃圾对象的产生,但该部分的垃圾对象出现在标记过程结束以后,CMS无法在当次收集过程中处理他们(只能下次垃圾收集时处理),因此称为浮动垃圾。因此,CMS必须预留足够的内存空间提供给用户线程使用,JDK6,默认启动阈值为 92%(该值需要根据生产环境变化,太高,有可能频繁并发失败):要是CMS运行期间预留的内存无法满足程序分配新对象,触发并发失败(Concurrent Mode Failure),这时候JVM启动预备方案:冻结用户线程,临时启动 Serial Old 来进行老年代的手机,这样停顿时间会很长。
- 大量空间碎片。空间碎片过多会导致大对象分配失败(老年代还有很多空间,但没有连续的大空间),而不得不提前触发 Full GC。CMS提供了参数 -XX:+UseCMS-CompactAtFullCollection 开关参数(默认开启,JDK9之后废弃),用于在CMS不得不Full GC时开启碎片的合并整理过程。但整理涉及到移动对象,STW,停顿时间会变长。
Garbage First (G1收集器)
目标是在延迟可控的范围内获取尽可能高的吞吐量
G1是面向堆内任何部分来组成回收集进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾最多,回收收益最大,这就是 G1 收集器的 Mixed GC 模式。
G1不再坚持分代划分,而是把连续的Java 堆划分为多个大小相等的独立区域(Region),每个 Region 根据需要版本新生代的Eden、Survivor或老年代。收集器能够对扮演不同角色的Region采用不同的策略去处理。这样无论是新对象还是已经存活了一段时间的对象、熬过多次收集的就对象都能获得很好的收集效果。
Region 中还有一类特殊的 Humonggous 区域,专门用来存放大对象。此处大对象,指的是内存大小超过一个 Region 容量一半的对象。每个Region的大小可以通过 -XX:G1HeapRegionSize 设定,取值范围为 1~32MB,且为2的N次幂。如果对象大小超过Region大小,将会被放到N个连续的 Humongous Region,G1的大多数行为将Humongous 作为老年代的一部分处理。
虽然 G1 仍然保留了新生代和老年代的概念,但新生代和老年代不再是固定的,他们都是一系列区域(不需要连续)的动态集合。G1 之所以能够建立可预测的停顿时间模型,是因为他将Region 作为可回收的最小单元。更具体的操作是:让G1 去跟踪各个Region 里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需要的经验值,然后在后台维护一个优先级列表,每次根据用户设定的允许的收集停顿时间(-XX:MaxGCPauseMills,默认200ms)优先处理回收价值最大的Region。这也是 “Garbage First“ 的由来。该方式保证了G1在有限的事件内获取尽可能高的收集效率。
G1收集器大致可以分为以下四个步骤:
只有并发标记可以与用户线程并发进行。
CMS 与 G1 比较
G1 的优点
G1 的缺点:
CMS 更适合在小内存应用上,而G1在大内存应用上能发挥更多优势。两者的内存临界点为 6 GB 到 8GB。
相关文章
- 暂无相关文章
用户点评