了解JVM垃圾回收器
1. 7种垃圾回收器
种类 | 回收器名字 |
---|---|
串行 | Serial ,Serial Old |
并行 | ParNew,Parallel SCavenge,Parallel Old |
并发: | CMS,G1 |
按照分区的划分
Young G : Serial ,Parallel SCavenge,ParNew,
Old G: Serial Old,Parallel Old,CMS
G1是两个都可以,
可以利用-XX:+PrintCommandLineFlags -XX:+UseXXXGC 这个可以设置项目利用哪个垃圾回收器并打印看看
所有的垃圾回收器都会Stop the World,就是在回收的时候暂停其它线程除垃圾回收线程外
2. Serial与Serial Old
-XX:+UseSerialGC 切换为Serial回收器
他们的关系一般是搭配的,新生代用Serial,老年代用Serial Old
优势 | 单线程下简单高效,没有线程开销,专心垃圾回收 |
---|---|
Serial | 单线程下性能更好,而且是采用的复制算法串行回收 |
Serial Old | 也是单线程下比较好,但是是老年代回收器,采用的标记压缩算法 |
特点 | 只使用一个CPU或一条收集线程去回收垃圾,更重要是回收时必须暂停其它所有的工作,直到收集结束 |
场景 | 适用于Client 的jvm占用不大,单线程 |
串行 | 两者都是 |
3. ParNew 新生代回收器
-XX:+UseParNewGC 切换为ParNew回收器
jdk9以后都没有搭配的老年代回收器所以就退役了,jdk9之前可以和CMS或者Serial Old搭配
它是并行的,对于新生代,回收次数频繁,使用并行方式高效
对于老年代,回收次数少,使用串行方式节省资源,因为并行的话会切换上下文,不过性能好的话多核也可以并行
采用的复制算法并行回收,采用stop the world的方式内存回收
4. Parallel Scavenge和Parallel Old
java8默认是这两个回收器
二者可以相互激活 -XX:+UseParalleGC 或者 -XX:+UseParallOldeGC
-XX:+ParallelGCThreads 设置年轻代并行回收线程数,最好与cpu个数相等,多了到时候线程切换上下文耗时,少了又浪费资源
注重吞吐量!!!
并行的 注重吞吐量,主要是可以自适应调节吞吐量(调节分代的大小,Eden和幸存的比例 ,晋升老年代的年龄),这也是和ParNew不同的地方
这两个回收器一般出现都是一套,新生代用Parallel Scavenge(复制算法),老年代用Parallel Old(标记压缩算法)
适用场景
不适合频繁交互的任务,适合后台运行比如批处理,大量计算,订单处理等的时候
为什么老年代不用Serial,串行效率不是更高
因为它注重吞吐量,高性能的服务器还是用并行的不用串行的Serial,不然浪费资源
5. CMS回收器
-XX:+UseConcMarkSweepGC 切换CMS回收器 JDK14已经移除了
注重响应时间!!!
并发的老年代的回收器,采用标记-清除算法。用户线程和垃圾回收同时执行,对响应时间上更好,适合与用户交互,缩短stop the world的时间
有五个过程 初始标记(stop)-并发标记-重新标记(stop短)-并发清除-重置线程
我们来讲一下它的过程:
- 初始标记:所有用户线程stop 然后标记出可达性对象,马上恢复用户,速度很快
- 并发标记:把可达性对象遍历根节点,但不stop,跟用户线程并发运行,耗时很长
- 重新标记:修正并发标记,因为用户运行期间对象可能会变动为垃圾,垃圾也可能被引用,先stop用户活动线程,不然边活动产生垃圾很难标记,时间很短
- 并发清除:清理一些标记阶段判定的垃圾,释放内存,跟存活对象无关系所以不用stop the world
- 重置线程
初始标记和重新标记都要stop the world,但是时间很短,几乎不影响,从上面我们就可以看出大部分过程都是和用户线程一起执行,只有短暂的stop这就是低延迟
在这个过程中基本没有中断,需要保证可用内存大小,内存到一定量就开始回收,但是如果内存不够CMS运行的时候就启动备用方法改Serial Old用标记清理stop收集,效率特别慢了
为什么不改成标记压缩算法,还能整理内存空间
因为在并发清除的过程,用户程序是并发的所以不能改变内存地址,会出问题标记整理更适合stop the world
好处 | 低延迟,并发收集 |
---|---|
缺点 | 1. 标记清除会产生内存碎片用户线程内存不足会提前重GC 2. 会占用一部分资源导致用户线程变慢,总吞吐量有所降低 3. 无法清理浮动垃圾,在并发标记的时候用户线程运行过程诞生新垃圾,修正标记只是对之前的可达性对象修正,新的垃圾没被标记到, |
6. G1回收器 JDK9默认回收器
特点是:分区域分代,年轻代和老年代兼顾
并行回收器,分出了很多区域,根据允许的收集时间,优先回收价值最大的区域
侧重点是垃圾多的区域,垃圾优先
年轻代(Eden-To-From)占1/3- 老年代占2/3
年轻代里面又是 8/10:1/10:1/10
优势:
- 并行与并发
并行多个垃圾回收线程同时回收垃圾,STW - 分代收集
逻辑上分成EDEN和Survivor,逻辑上区域包括年轻代和老年代 - 空间整合
可以在若干次GC后进行一个标记整理 - 可预测的停顿时间模型
缩小回收范围,贪心法,对垃圾堆价值最大的先回收
保证了有限时间回收了最大的垃圾
**缺点:**垃圾回收过程内存占用比CMS高,运行时额外负载比CMS高
STW加多个回收线程,消耗大,所以小内存还是CMS好
三种回收模式:轻GC,重GC,MIXGC
使用场景是大内存和多处理器的机器
G1中会创一个H区来存放短时存在的大对象,一个放不下就找连续的H区
年轻代的Eden用光时会轻GC给幸存区,当活下来的年龄达到15次后就会移动到老年区,堆内存达到45的时候重GC一次
RemberSet
因为对象可能被其它区的对象引用,但是回收不可能全盘扫描来判断对象的存活,RemeberSet防止全盘扫描
,每个区都有RemeberSet,会去记录对象被哪些区的对象引用,如果是其它区的就用CardTable记录到RSet,将垃圾回收范围扩大一个Rset
更多相关了解可以看jvm知识