在jvm中,实现了多种垃圾收集器,包括:串行垃圾收集器、并行垃圾收集器、CMS(并发)垃圾收集器、G1垃圾收集器,接下来,咱们一个个的了解学习。java
串行垃圾收集器web
串行垃圾收集器,是指使用单线程进行垃圾回收,垃圾回收时,只有一个线程在工做,算法
而且java应用中的全部线程都要暂停,等待垃圾回收的完成。这种现象称之为STW(Stop-The-World)。多线程
对于交互性较强的应用而言,这种垃圾收集器是不可以接受的。并发
通常在Javaweb应用中是不会采用该收集器的。oracle
编写测试代码dom
package com.wish; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Random; public class TestGC { public static void main(String[] args) throws Exception { List<Object> list = new ArrayList<Object>(); while (true) { int sleep = new Random().nextInt(100); if (System.currentTimeMillis() % 2 == 0) { list.clear(); } else { for (int i = 0; i < 10000; i++) { Properties properties = new Properties(); properties.put("key_" + i, "value_" + System.currentTimeMillis() + i); list.add(properties); } } // System.out.println("list大小为:" + list.size()); Thread.sleep(sleep); } } }
设置垃圾回收为串行收集器jvm
在程序运行参数中添加2个参数,以下:性能
# 为了测试GC,将堆的初始和最大内存都设置为16M -XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m
启动程序,能够看到下面信息:学习
GC日志信息解读:
年轻代的内存GC先后的大小:
并行垃圾收集器
并行垃圾收集器在串行垃圾收集器的基础之上作了改进,将单线程改成了多线程进行垃圾回收,这样能够缩短垃圾回收的时间。
(这里是指,并行能力较强的机器)
固然了,并行垃圾收集器在收集的过程当中也会暂停应用程序,这个和串行垃圾回收器是同样的,只是并行执行,速度更快些,暂停的时间更短一些。
ParNew垃圾收集器
ParNew垃圾收集器是工做在年轻代上的,只是将串行的垃圾收集器改成了并行。
经过-XX:+UseParNewGC参数设置年轻代使用ParNew回收器,老年代使用的依然是串行收集器。
测试:
#参数 -XX:+UseParNewGC -XX:+PrintGCDetails -Xms16m -Xmx16m
由以上信息能够看出, ParNew: 使用的是ParNew收集器。其余信息和串行收集器一致。
ParallelGC垃圾收集器
ParallelGC收集器工做机制和ParNewGC收集器同样,只是在此基础之上,新增了两个和系统吞吐量相关的参数,使得其使用起来更加的灵活和高效。
相关参数以下:
通常用于,手动调整参数比较困难的场景,让收集器自动进行调整。
测试
#参数 -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xms16m -Xmx16m
启动
有以上信息能够看出,年轻代和老年代都使用了ParallelGC垃圾回收
CMS垃圾收集器
CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,经过参数-XX:+UseConcMarkSweepGC进行设置。
CMS垃圾回收器的执行过程以下:
测试
#设置启动参数 ‐XX:+UseConcMarkSweepGC ‐XX:+PrintGCDetails ‐Xms16m ‐Xmx16m
由以上日志信息,能够看出CMS执行的过程。
G1垃圾收集器
G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器,oracle官方计划在jdk9中将G1变成默认的垃圾收集器,以替代CMS。
G1的设计原则就是简化JVM性能调优,开发人员只须要简单的三步便可完成调优:
1. 第一步,开启G1垃圾收集器
2. 第二步,设置堆的最大内存
3. 第三步,设置最大的停顿时间
G1中提供了三种模式垃圾回收模式,Young GC、Mixed GC 和 Full GC,在不一样的条件下被触发。
原理
G1垃圾收集器相对比其余收集器而言,最大的区别在于它取消了年轻代、老年代的物理划分,
取而代之的是将堆划分为若干个区域(Region),这些区域中包含了有逻辑上的年轻代、老年代区域。
这样作的好处就是,咱们不再用单独的空间对每一个代进行设置了,不用担忧每一个代内存是否足够。
在G1划分的区域中,年轻代的垃圾收集依然采用暂停全部应用线程的方式,将存活对象拷贝到老年代或者Survivor空间,
G1收集器经过将对象从一个区域复制到另一个区域,完成了清理工做。
这就意味着,在正常的处理过程当中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有cms内存碎片问题的存在了。
在G1中,有一种特殊的区域,叫Humongous区域。
Young GC
Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。
Remembered Set(已记忆集合)
在GC年轻代的对象时,咱们如何找到年轻代中对象的根对象呢?
根对象多是在年轻代中,也能够在老年代中,那么老年代中的全部对象都是根么?
若是全量扫描老年代,那么这样扫描下来会耗费大量的时间。
因而,G1引进了RSet的概念。它的全称是Remembered Set,其做用是跟踪指向某个堆内的对象引用。
每一个Region初始化时,会初始化一个RSet,该集合用来记录并跟踪其它Region指向该
Region中对象的引用,每一个Region默认按照512Kb划分红多个Card,因此RSet须要记录的东西应该是 xx Region的 xx Card。
Mixed GC
当愈来愈多的对象晋升到老年代old region时,为了不堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,
即Mixed GC,该算法并非一个Old GC,除了回收整个YoungRegion,还会回收一部分的Old Region,
这里须要注意:是一部分老年代,而不是所有老年代,能够选择哪些old region进行收集,从而能够对垃圾回收的耗时时间进行控制。
也要注意的是Mixed GC 并非 Full GC。
MixedGC何时触发?
由参数 -XX:InitiatingHeapOccupancyPercent=n 决定。默认:45%,该参数的意思是:当老年代大小占整个堆大小百分比达到该阀值时触发。
它的GC步骤分2步:
1.全局并发标记(global concurrent marking)
2. 拷贝存活对象(evacuation)
全局并发标记
全局并发标记,执行过程分为五个步骤:
拷贝存活对象
Evacuation阶段是全暂停的。该阶段把一部分Region里的活对象拷贝到另外一部分Region中,从而实现垃圾的回收清理。
G1收集器相关参数
测试
#参数 ‐XX:+UseG1GC ‐XX:MaxGCPauseMillis=100 ‐XX:+PrintGCDetails ‐Xmx256m
对于G1垃圾收集器优化建议