Java垃圾收集器的一些总结
2020-03-23 本文已影响0人
西瓜程序员
GC
1 常见的GC收集器
分代收集阶段
一.新生代收集器
1 Serial New
- jdk1.5默认收集器
- 基于复制算法
- 单线程
- 存在stop the world
2 Parallel New
- 对Serial的改进,ParNew是并行的,在多CPU场景性能更好
- 这种收集器在采用CMS(后文会讲到,一种老年代收集器)时,默认新生代会采用ParNew收集器
- 如果CPU数量为1个或者少于4个时,该种收集器的性能并不会比Serial要好。因为除去上下文切换,以及占用用户线程CPU时间片,导致用户线程被拖慢。
3 Parallel Scavenge
- 与前两者的区别:关注吞吐量而不是延迟。是吞吐量优先的收集器
- 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
- 在实现上比前两种改进了很多,但是一直到1.6以后才真正用起来,这是因为,它不能跟CMS收集器一起配合工作。在此之前,使用该种新生代收集器的话,老年代收集器必须使用Serial Old收集器。
二、老年代收集器
1 Serial Old
- jdk1.2以前的默认收集器
- 使用标记-整理算法
- 单线程
- 存在stop the world
2 Parallel Old
- Serial的多线程版本
- 使用标记-整理算法
3 CMS
-
并发收集器
-
基于标记-清除算法
-
收集过程
-
第一步:初始标记
- stop the world
- 做GC Root可达性的初始标记
-
第二步:并发标记
-
第三步:重新标记
- stop the world
- 第三步标记第二步中变动的对象
-
第四步:并发清除
- 耗时最长的第二步和第四部是可以与用户线程并发执行的
-
-
它的优点比较明显,就是能够全局上与用户线程并发执行。是第一款真正意义上的并发收集器。
-
缺点:
- <u style="box-sizing: border-box; margin-top: 0px;">内存碎片</u>:内存碎片的存在会导致在剩余空间还很多的情况下使得大对象无法分配,而提前触发一次full gc。full gc导致的停顿时间会很长。影响体验。
- <u style="box-sizing: border-box; margin-top: 0px;">浮动垃圾</u>:由于清除的时候是并发清除的,这时候用户态产生的垃圾必然无法在本次收集过程中收集掉。也就会产生浮动垃圾。如果之前收集没有收集到足够多有效空间的话也会提前触发full gc的过程。
非分代收集
1. G1(Garbage First)
-
内存空间被分割成一个个的<mark style="box-sizing: border-box; background-color: rgb(255, 255, 0); color: rgb(0, 0, 0);">Region区</mark>,所谓新生代和老年代,都是由一个个region组成的
-
同时G1也不需要跟别的收集器一起配合使用,自己就可以搞定所有内存区域。整体上来讲不是一个分代收集器,是一个通吃收集器
-
采用标记-整理算法
-
G1的工作过程
- <u style="box-sizing: border-box; margin-top: 0px;">初始标记</u>:这个过程跟CMS第一个过程差不多,只是标记一下GC Root关联的对象。
- <u style="box-sizing: border-box; margin-top: 0px;">并发标记</u>:这个过程时间比较久,分析GC Root到所有对象的可达性分析。如果从GC Root节点开始遍历所有对象会比较耗时,实际上JVM也不是这么做的。JVM是使用Remembered Set保存了对象引用的调用信息,在可达性分析的时候只需要同时遍历remembered set就好了,不需要从根节点开始挨个遍历。
- <u style="box-sizing: border-box; margin-top: 0px;">最终标记</u>:由于并发标记阶段,用户线程仍然在工作,会对标记产生一些偏差,这时候需要通过remembered set log来记录这些改变,在这个阶段将改变合并到remembered set中。完成最终标记。
- <u style="box-sizing: border-box; margin-top: 0px;">筛选清除</u>:通过标记整理的算法,根据用户配置的回收时间,和维护的优先级列表,优先收集价值最大的region。收集阶段是基于标记-整理和复制算法实现。
2. ZGC
-
优点:无碎片,时间可控,超大堆
-
与标记对象的传统算法相比,ZGC在指针上做标记,在访问指针时加入Load Barrier(读屏障),比如当对象正被GC移动,指针上的颜色就会不对,这个屏障就会先把指针更新为有效地址再返回,也就是,永远只有单个对象读取时有概率被减速,而不存在为了保持应用与GC一致而粗暴整体的Stop The World。
-
八大特征:
- 1. 所有阶段几乎都是并发执行的:
- 2. 并发执行的保证机制,就是Colored Pointer 和 Load Barrier
- 3. 像G1一样划分Region,但更加灵活
- 4. 和G1一样会做Compacting-压缩
- 5. 没有G1占内存的Remember Set,没有Write Barrier的开销
- 6. 支持Numa架构
- 7. 并行
- 8. 不分代