1.什么是分代收集理论?
目前虚拟机的垃圾收集采用的都是分代收集算法:根据对象存活周期的不同将内存分为几块,再根据每一块内存的特性,实行不同的垃圾收集算法进行收集。
2.常见的垃圾收集算法
常见的垃圾收集算法有标记-复制算法,标记-清除算法,标记-整理算法。
标记-复制算法:它会将内存空间划分为大小相同的两块,每次只使用其中的一块,当这一块的内存使用完后,将还存活的对象复制到另一块去,然后再把使用完的这一块清理干净,这样每次回收内存都是对内存区域的一半进行回收。
![](https://img-blog.csdnimg.cn/2aee605e661946f1abb67735ec76f311.png)
标记-清除算法:该算法分为标记和清除两个阶段,标记存活的对象,统一回收所有未被标记对象(常用),当然反向标记也行。这种算法会带来两个问题,效率问题(遇到大量需要标记的对象,效率不高),空间问题(标记清楚后会产生大量不连续的碎片)。
![](https://img-blog.csdnimg.cn/84a08d5135e14e81aa27273dd45fc398.png)
标记-整理算法:这一算法是根据老年代的特点出现的一种标记算法,标记过程和标记清除算法一致,但是后续是将所有存活的对象向一端移动,然后直接清除掉端边界以外的内存。
![](https://img-blog.csdnimg.cn/fc92ecfa96dc4851ab1f3a6e82968de5.png)
3.常见的垃圾收集器有哪些?
![](https://img-blog.csdnimg.cn/111bada45d7c427d8c6cfdc3c6689f8b.png)
如上图所示,是我们常见的几种垃圾收集器,接下来我们来分别介绍下:
1:Serial 收集器(串行) 标记复制算法
JVM参数: -XX:+UseSerialGC -XX:+UseSerialOldGC
是最基本最悠久的垃圾收集器,它是单线程的在运行时会产生Stop The World(暂停所有其他工作线程) ,直到它收集结束。 SerialOld 标记整理算法 则是Serial收集器的老年代版本,它同样是一个单线程收集器。它主要有两大用途:一种用途是在JDK1.5 以及以前的版本中与ParallelScavenge收集器搭配使用,另一种用途是作为CMS收集器的后备方案。
![](https://img-blog.csdnimg.cn/93bd3cd5020f4c1a87474f4bc66d93fd.png)
特点总结:简单高效,但是产生stw时间长用户体验感不好。
2:Parallel Scavenge 收集器 jdk 1.8默认的收集器
新生代采用复制算法,老年代采用标记-整理算法
JVM参数:-XX:+UseParallelGC(年轻代) -XX:+UseParallelOldGC(老年代)
Parallel收集器其实就是Serial的多线程版本
![](https://img-blog.csdnimg.cn/50cebbc3cbf84d2bb9be28e9dda92cad.png)
特点总结:吞吐量高 CPU的利用效率高
3:ParaNew 收集器、
ParNew收集器其实
跟Parallel收集器很类似
,区别主要在于它可以和CMS收集器配合使用
新生代采用复制算法,老年代采用标记-整理算法
JVM参数:
-XX:+UseParNewGC
4:CMS收集器 用于老年代
JVM参数:
-XX:+UseConcMarkSweepGC
CMS (Concurrent Mark Sweep) 收集器是一种以获取最短回收停顿时间为目标的收集器,它采用的是标记清除算法,它的整个步骤如下图所示:
初始标记:暂停所有的其他线程,STW 并记录下gc roots直接能引用的对象,速度很快
并发标记:从GC Roots的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但
是不需要停顿用户线程, 可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有
导致已经标记过的
对象状态发生改变。
重新标记:
就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对
象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间
短。主要用到三色标记里的
增量更新算法做重新标记。
并发清理
:开启用户线程,同时GC线程开始对未标记的区域做清理。这个阶段新增的对象会被三
色标记算法标记成黑色 不做处理,留到下一次GC在进行处理。
并发重置:重置本次GC中标记的数据,清除标记。
特点:对CPU资源敏感会和服务抢资源;无法处理浮动垃圾,只能等到下次GC再做处理;它采用
的标记清除算法,会造成大量空间碎片
XX:+UseCMSCompactAtFullCollection
可以让jvm在执行完标记清除后再做整理;
可能在并发标记和并发清理的过程中再次出发full gc 导致产生
concurrent mode failure ,此时则
会进入STW 并且使用Serial Old 垃圾收集器来回收。
CMS的相关核心参数
1. -XX:+UseConcMarkSweepGC:启用cms
2. -XX:ConcGCThreads:并发的GC线程数
3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一 次
5. -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
6. -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值
(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续
则会自动调整
7. -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对
年轻代的引 用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
8. -XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
9. -XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW