JVM垃圾回收几种常见算法和常见收集器
Posted java技术阅读
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM垃圾回收几种常见算法和常见收集器相关的知识,希望对你有一定的参考价值。
标记——清除算法
标记——清除算法是几种GC算法中最基础的算法,标记和清除效率不高,产生大量不连续的内存碎片,导致创建大对象时找不到连续的空间。后续的收集算法都是基于这种思想并对其不足进行改进而实现的。
复制算法
将可用内存按容量分为大小相等的两块,每次只使用其中一块,当这一块的内存用完,就将还存活的对象复制到另外一块内存上,然后再把已使用过的内存空间一次清理掉。
现在的商业虚拟机都采用这种收集算法来回收新生代,但并不是将内存划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survior 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另一块 Survivor 空间上,最后清理 Eden 和 使用过的那一块 Survivor。HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90 %。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时需要依赖于老年代进行分配担保,也就是借用老年代的空间。
标记——整理算法
标记——整理算法不会像复制算法那样随着存活对象的升高而降低效率,不像标记-清除算法那样产生不连续的内存碎片。但是,除了像标记-清除算法的标记过程外,还多了一步整理过程,效率更低。
分代收集算法
新生代:由于新生代产生很多临时对象,大量对象需要进行回收,所以采用复制算法是最高效的。
I 垃圾收集器
图中展示了7种作用于不同分代的收集器:serial收集器、parNew收集器、parallel scavenge收集器、serial old 收集器、parallel old收集器、cms收集器、g1收集器。如果两个收集器之间存在连线,则说明它们可以搭配使用。
吞吐量:即CPU用于运行用户代码的时间与CPU总消耗时间的比值(吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 ))。例如:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%。
串行收集器(Serial/Serial old)
Serial:使用在新生代中,采用复制算法,实现相对简单,逻辑处理特别高效,且没有线程切换的开销;
Serial old:使用在老年代中,采用标记——整理算法,由于Serial old通常使用会比Serial垃圾回收更长,在堆空间比较大的运用程序中,一旦Serial old启动,应用程序很可能会因此停顿几秒甚至更长时间。
参数配置:
-XX:+UseSerialGC 表示新生代、老年代都使用串行回收器(上图所示)。
新生代并行收集器(parNew)
ParNew也是独占式的回收器,在收集过程中,应用程序会全部暂停。但由于ParNew使用多线程进行垃圾回收,因此,在并发能力比较强的 CPU 上,它产生的停顿时间要短于串行回收器,而在单 CPU 或者并发能力较弱的系统中,ParNew的效果不会比串行回收器好,由于多线程的压力,它的实际表现很可能比串行回收器差。
配置参数:
-XX:+UseParNewGC 表示新生代使用并行收集器,老年代使用串行收集器(上图所示)。
-XX:ParallelGCThreads 指定并行收集器工作时的线程数。一般,最好与 CPU 数量相当,避免过多的线程数影响垃圾收集性能。在默认情况下,当 CPU 数量小于 8 个,ParallelGCThreads 的值等于 CPU 数量,大于 8 个,ParallelGCThreads 的值等于 3+[5*CPU_Count]/8]。
并行回收收集器(parallel scavenge/parallel old)
Parallel Scavenge:属于新生代收集器采用复制算法的收集器;Parallel old:属于老年代收集器采用标记——整理算法的收集器。
配置参数:
-XX:+MaxGCPauseMills 设置最大垃圾收集停顿时间,它的值是一个大于 0 的整数。收集器在工作时会调整 Java 堆大小或者其他一些参数,尽可能地把停顿时间控制在 MaxGCPauseMills 以内。如果希望减少停顿时间,而把这个值设置得很小,为了达到预期的停顿时间,JVM 可能会使用一个较小的堆 (一个小堆比一个大堆回收快),而这将导致垃圾回收变得很频繁,从而增加了垃圾回收总时间,降低了吞吐量。
-XX:+GCTimeRatio 设置吞吐量大小,它的值是一个 0-100 之间的整数。假设 GCTimeRatio 的值为 n,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集。比如 GCTimeRatio 等于 19,则系统用于垃圾收集的时间不超过 1/(1+19)=5%。默认情况下,它的取值是 99,即不超过 1%的时间用于垃圾收集。
-XX:+UseParallelOldGC 在新生代和老生代都使用并行回收收集器,对吞吐量敏感的系统中,可以考虑使用(上图所示)。
-XX:ParallelGCThreads 也可以用于设置垃圾回收时的线程数量。
垃圾回收篇幅过长,下文继续讲解最后的内容cms收集器和g1收集器。
以上是关于JVM垃圾回收几种常见算法和常见收集器的主要内容,如果未能解决你的问题,请参考以下文章