05-jvm-GC算法-实际应用

垃圾收集器

若是说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现
复制代码

性能度量指标

  • 吞吐量:表示系统减去系统回收时间占总时间的比率,好比,系统运行了100秒,垃圾回收占用了1秒,那么吞吐量就是(100-1)/100 = 99%算法

  • 垃圾回收消耗:和吞吐量相反,垃圾回收器消耗指的是垃圾回收器耗时与系统运行总时间的比值编程

  • 停顿时间:指垃圾回收器运行的时候,系统停顿的时间服务器

  • 回收频率:指垃圾回收器多长时间运行一次,通常来讲,对于固定的应用而言,垃圾回收器的频率应该越低越好,一般增长堆空间能够有效的下降垃圾回收发生的频率,可是可能会增长回收产生的停顿时间多线程

  • 反应时间:当一个内存对象被标记为垃圾对象后到这个对象真正回收所产生的时间并发

    根据这几个指标,咱们能够知道,垃圾回收性能好的表现是:吞吐量高,垃圾回收消耗低,停顿时间少,回收频率低,反应时间快。可是,并无这么完美的性能表现,这几个指标有些是互斥的,好比要下降回收频率,就要扩大空间,可是就会增长停顿时间;一样要想反应时间快,就必需要提升回收频率。因此,这些性能的追求就是一个博弈平衡的过程,咱们能够根据咱们追求的某一方面来进行调优,好比,对于客户端应用而言,应该尽量下降其停顿时间,给用户良好的使用体验,为此,能够牺牲垃圾回收的吞吐量;对服务端程序来讲,可能会更加关注吞吐量。jvm

按执行机制划分Java有四种类型的垃圾回收器

image

  1. 串行垃圾回收器(Serial Garbage Collector)
  2. 并行垃圾回收器(Parallel Garbage Collector)
  3. 并发标记扫描垃圾回收器(CMS Garbage Collector)
  4. G1垃圾回收器(G1 Garbage Collector)
  • 每种类型都有各自的优点和劣势,在很大程度上有所不一样,能够给咱们提供彻底不一样的应用程序性能
  • 咱们编程的时候,能够经过向jvn传递参数,选择正确的垃圾回收器的类型
Serial收集器 (串行垃圾回收器)

image
image

  • 串行收集器是最古老、最稳定以及效率高的垃圾回收器。布局

  • 使用单线程进行垃圾回收,独占式垃圾回收性能

  • 串行垃圾回收器经过持有应用程序全部的线程进行工做。它为单线程环境设计,只使用一个单独的线程进行垃圾回收,经过冻结全部应用程序线程进行工做,因此可能不适合服务器环境spa

  • 它最适合的是简单的命令行程序(单CPU、新生代空间较小及对暂停时间要求不是很是高的应用)。是client级别默认的GC方式。命令行

  • 新生代、老年代使用串行回收;新生代复制算法、老年代标记-压缩;垃圾收集的过程当中会Stop The World(服务暂停)

    参数控制: -XX:+UseSerialGC 串行收集器

ParNew收集器 (串行垃圾回收器)

image

image

  • ParNew收集器其实就是Serial收集器的多线程版本。新生代并行,老年代串行;新生代复制算法、老年代标记-压缩

  • 只有他能与CMS收集器配合工做。

  • 参数控制:

    -XX:+UseParNewGC ParNew收集器 -XX:ParallelGCThreads 限制线程数量 -XX:+UseParNewGC:新生代使用并行收集器,老年代使用串行回收器。 -XX:+UseConcMarkSweepGC:新生代使用并行回收器,老年代使用CMS

  • 并行收集器工做时的线程数量可使用 -XX:ParallelGCThreads 参数指定。通常最好与CPU数量至关,避免过多的线程数,影响垃圾收集性能

  • 在默认状况下,当CPU数量小于8个时,ParallelGCThreads 的值等于 CPU 数量;当 CPU 数量大于8个时,ParallelGCThreads 的值等于 3+[(5*CPU_Count)/8]

Parallel Scavenge 收集器 (并行垃圾回收器)
  • 并行垃圾回收器也被称之为:吞吐量收集器(throughput collector)

  • 他是jvm默认的垃圾回收器

  • 与串行垃圾回收器不一样的是它使用多线程进行垃圾回收,使用的是复制算法

  • 类似的是执行垃圾回收的时候,他也会冻结全部的应用程序线程

  • 使用与CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式。

  • 参数控制

    -XX:+UseParallelGC 新生代使用并行回收收集器,老年代使用串行回收器。 -XX:ParallelGCThreads=4 指定线程数

Parallel Old 收集器并行垃圾回收器)

image

  • Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器是在JDK 1.6中才开始提供

  • 参数控制

    -XX:+UseParallelOldGC 使用Parallel收集器+ 老年代并行

并发标记扫描垃圾回收器
  • 使用多线程扫描内存,标记须要清理的实例,而且清理已经标记的实例。
  • 并发标记扫描垃圾回收器只会在如下两种状况持有应用程序的全部线程
    • 标记的引用对象在永久(Tenured)区域
    • 在进行垃圾回收的时候,堆内存的数据被并发的改变。

相比并行垃圾回收器,并发标记扫描垃圾回收器使用更多的CPU来确保程序的吞吐量。若是咱们能够为了更好的程序性能分配更多的CPU,那么并发标记上扫描垃圾回收器是更好的选择相比并发垃圾回收器。

经过JVM参数 XX:+USeParNewGC 打开并发标记扫描垃圾回收器。

CMS收集器

image

  • CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器
  • 从名字(包含“Mark Sweep”)上就能够看出CMS收集器是基于“标记-清除”算法实现的
  • 它的运做过程相对于前面几种收集器来讲要更复杂一些,整个过程分为4个步骤,包括:
    • 初始标记(CMS initial mark)
    • 并发标记(CMS concurrent mark)
    • 从新标记(CMS remark)
    • 并发清除(CMS concurrent sweep)
  • 其中初始标记、从新标记这两个步骤仍然须要“Stop The World”
  • 初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,
  • 并发标记阶段就是进行GC Roots Tracing的过程
  • 从新标记阶段则是为了修正并发标记期间,因用户程序继续运做而致使标记产生变更的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但远比并发标记的时间短
  • 因为整个过程当中耗时最长的并发标记和并发清除过程当中,收集器线程均可以与用户线程一块儿工做,因此整体上来讲,CMS收集器的内存回收过程是与用户线程一块儿并发地执行。老年代收集器(新生代使用ParNew)
优势:

并发收集、低停顿

缺点:

产生大量空间碎片、并发阶段会下降吞吐量

参数控制:
  1. -XX:+UseConcMarkSweepGC 使用CMS收集器
  2. -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;整理过程是独占的,会引发停顿时间变长
  3. -XX:+CMSFullGCsBeforeCompaction 设置进行几回Full GC后,进行一次碎片整理
  4. -XX:ParallelCMSThreads 设定CMS的线程数量(通常状况约等于可用CPU数量)
G1收集器
  • G1是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是将来能够替换掉JDK1.5中发布的CMS收集器
  • 空间整合,G1收集器采用标记整理算法,不会产生内存空间碎片。分配大对象时不会由于没法找到连续空间而提早触发下一次GC。
  • 可预测停顿,这是G1的另外一大优点,下降停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能创建可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片断内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已是实时Java(RTSJ)的垃圾收集器的特征了。
  • 使用G1收集器时,Java堆的内存布局与其余收集器有很大差异,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔阂了,它们都是一部分(能够不连续)Region的集合。
以上的垃圾回收器须要组合使用

image

经常使用的收集器组合
组合 新生代GC策略 老年老代GC策略 说明
组合1 Serial Serial Old Serial和Serial Old都是单线程进行GC,特色就是GC时暂停全部应用线程。
组合2 Serial CMS+Serial Old CMS(Concurrent Mark Sweep)是并发GC,实现GC线程和应用线程并发工做,不须要暂停全部应用线程。另外,当CMS进行GC失败时,会自动使用Serial Old策略进行GC
组合3 ParNew CMS 使用 -XX:+UseParNewGC选项来开启。ParNew是Serial的并行版本,能够指定GC线程数,默认GC线程数为CPU的数量。可使用-XX:ParallelGCThreads选项指定GC的线程数。若是指定了选项 -XX:+UseConcMarkSweepGC选项,则新生代默认使用ParNew GC策略。
组合4 ParNew Serial Old 使用 -XX:+UseParNewGC选项来开启。新生代使用ParNew GC策略,年老代默认使用Serial Old GC策略。
组合5 Parallel Scavenge Serial Old Parallel Scavenge策略主要是关注一个可控的吞吐量:应用程序运行时间 / (应用程序运行时间 + GC时间),可见这会使得CPU的利用率尽量的高,适用于后台持久运行的应用程序,而不适用于交互较多的应用程序。
组合6 Parallel Scavenge Parallel Old Parallel Old是Serial Old的并行版本
组合7 G1GC G1GC -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC #开启; -XX:MaxGCPauseMillis=50 #暂停时间目标; -XX:GCPauseIntervalMillis=200 #暂停间隔目标; -XX:+G1YoungGenSize=512m #年轻代大小; -XX:SurvivorRatio=6 #幸存区比例
相关文章
相关标签/搜索