|
Java发展至今,已经推出了好几代垃圾收集器,包括Serial、ParNew、Parallel、CMS、G1以及Java11中最新的ZGC,每一代GC都对前一代存在的问题做出了很大的改善。
新生代使用的垃圾收集器主要有:
1.Serial收集器
2.ParNew收集器
3.Parallel scavenge收集器
Serial收集器:
1.单线程收集器,在单核CPU架构下,JDK3之前新生代的回收器的唯一选择、
2.它与应用线程的执行是串行的,也就是说,执行应用线程的时候,不会执行GC,执行GC的时候,不能执行应用线程
ParNew收集器
1.就是serial回收器的多线程版本,有很多的代码都是和serial收集器公用的
2.在进行回收的过程中仍然会暂停用户线程(STW),然后利用多核CPU的能力,采用多线程方式进行垃圾回收
Parallel scavenge收集器
自适应调节策略:
老年代:
老年代使用的垃圾收集器主要有:
1.Seria-old收集器
2.Parallel Old收集器
3.CMS收集器
Seria-old收集器
1.serial收集器的老年代版本,同样还是使用单线程进行垃圾回收
2.它存在的主要意义是,在JVM运行在client模式下,配合新生代的serial收集器一起使用
3.它还可以作为CMS垃圾回收器的后备垃圾回收器
Parallel Old收集器
1.这个回收器是Parallel scavenge的老年代版本,经常和Parallel scavenge一起使用在对内存比较敏感和对吞吐量比较高的场合下使用
2.使用多线程和“标记-整理”算法,这个收集器是在JDK6中才开始提供
CMS收集器
1.CMS是HotSpot在JDK5推出的第一款真正意义上的并发(Concurrent)收集器,第一次实现了让垃圾收集线程与用户线程(基本上)同时工作
2.CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器
3.目前很大一部分的Java应用都集中在互联网站或B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验
CMS收集器具体的过程
1.初始标记:只标记根节点直接关联的引用对象,需要暂停用户线程(时间短)
2.并发标记:标记其他引用对象,可以跟用户线程并发同时执行
3.重新标记:暂停用户线程,对并发标记期间新增加的引用关系变化再次标记(时间短)
4.并发清除:跟用户线程并发进行
CMS主要的有点提供了一个并发的能力,对用户程序打扰较小。但是,也有一些显而易见的缺点:
1.跟用户线程竞争资源
2.在并发清除垃圾阶段,由于用户线程还在执行,要预留一定的空间给用户线程进行使用,所以收集器一定不能在老年代已经占用100%的情况下再进行垃圾收集(没内存空间了)
3.因为这个垃圾回收器是使用的标记-清除算法,所以会产生大量的内存碎片
CMS收集器的缺点的人工干预:
1.使用-XX:CMSInitiatingOccupancyFraction来指定老年代到达多少的时候触发垃圾回收,JDK6之后默认为92,就是在老年代的空间已经占用92%的时候,就会触发一次垃圾回收
2.这个值如果设置的太高,就会出现并发清理的时候,用户线程并发执行没有足够的空间分配对象而造成内存分配失败的情况发生
3.如果发生分配失败,则会出现Concurrent Model Failure,那么老年代收集器就会自动转换使用serialOld收集器进行回收,从而导致用户线程的停顿时间变长,所以这个值设置的合理很重要
新一代垃圾回收器:G1(非常厉害)
1.空间整合:G1收集器采用标记-整理算法,不会产生内存空间碎片
2.它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔阂了,它们都是一部分可以不连续Region的集合。红色为巨大的对象创建区域的。
默认垃圾回收器
|