JVM的GC算法及回收器

124 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

4.1.1 JVM的GC算法

jvm的基本算法: • 标记清除(Mark-Sweep) 一块内存中的,将要回收的数据,标记直接清除。

• 复制算法(Copying) ​ 将一片内存中的数据直接复制到另一块内存中,然后清理掉之前的内存区域。

• 标记压缩(Mark-Compact) ​ 将内存中的数据,标记集中移动到内存的一边,进行清理。

• 分代收集算法 ​ 是物理和逻辑上将内存堆划分年轻代,老年代,根据不同代中的对象清除时候使用什么算法来提出的一种算法。

• 引用计数法

总结:各种回收算法都有各自的优缺点,没有一种算法可以完全替代其他的算法,在具体的使用中应该结合具体的环境来选择

$mc:标记清除法、复制清除法、分代收集法、引用计算法

4.1.2 垃圾回收器

算法是GC的垃圾回收的策略,而垃圾收集器,就是根据算法来进行垃圾处理的具体实现。

• Serial收集器: ​ Serial(串行)垃圾收集器是最基本、发展历史最悠久的收集器,JDK1.3.1前是HotSpot新生代收集的唯一选择。 Serial收集器到JDK1.7为止,它依然是JAVA虚拟机运行在Client模式下的默认新生代收集器。它也有着优于其他收集器的地方:简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。在用户的桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百兆的新生代(仅仅是新生代使用的内存,桌面应用基本上不会再大了),停顿时间完全可以控制在几十毫秒最多一百多毫秒以内,只要不是频繁发生,这点停顿是可以接受的。所以,Serial收集器对于运行在来说是一个很好的选择。

• Serial Old收集器 ​ Serial Old 和Serial 相比就是应用在老年代的垃圾收集器,也是单线程,但是算法不是copy,而是Mark-Compact 标记整理算法,也是stw:暂停所有线程进行垃圾回收;所以 Serial 和Serial Old 组合使用,可用内存一般不大(几十M至一两百M)的服务器环境中,不适合当前的大内存了

• ParNew收集器 ​ ParNew垃圾收集器是Serial收集器的改进多线程版本(因为内存的不断增大),除了多线程外,其余的行为、特点和Serial收集器一样,实现算法跟Serial完全一样(copy算法),也是stw下执行; 但是如果CPU数量为1个或者少于4个时,该种收集器的性能并不会比Serial要好。因为除去上下文切换,以及占用用户线程CPU时间片,导致用户线程被拖慢 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作;CMS是HotSpot在JDK1.5推出的第一款真正意义上的并发(Concurrent)收集器,第一次实现了让垃圾收集线程与用户线程(基本上)同时工作;

• Parallel Old ​ 这个是Serial Old的多线程版本,应用在老年代的收集器,也是标记-整理算法,并且是stw的执行收集。但是如果CPU数量少的话性能一样不好。但是现在无论是PC还是server CPU数量都不再是性能瓶颈限制了,所以目前它跟Parallel Scavenge的配合是吞吐量优先场景的优先收集器选择。