目录
1、什么是垃圾
在JVM中,如果一个对象没有任何有效引用引用它,它就是垃圾。【说人话:就是生活中一件衣服没有任何活人可以穿,那它就是垃圾】
2、怎么找到垃圾
2.1 引用计数法
概念:记录引用当前对象的指针个数,如果这个值是0,那它就是垃圾。【说人话:我要扔一件衣服,突然我发现这件衣服我爸能穿、我弟弟也能穿,那这个引用数值就是2,谁都不能穿,就是0,就是垃圾】
存在的问题:如果能穿这件衣服的人都死了(java的循环引用),弟弟觉得爸爸能穿不要扔,爸爸觉得弟弟能穿不要扔,实际上都死了,可以扔,这时候无法用引用计数法命中。
2.2 可达性算法
概念:从头开始找,如果找不到,就是垃圾【说人话:有没有活人能穿,即1中所说的有效引用】
可以作为GCRoot的元素:线程栈变量、静态变量、常量池、JNI指针
3、怎么回收
3.1 、标记清除算法
实现方式:当某件衣服不能穿的时候,我们会先把他标记一下【放到一个麻袋里,都是不能穿的】
适用场景:存活对象多的时候,效率比较高【很好理解,需要标记的少】
特点:扫描两遍,先找到,再清除。
3.2、拷贝算法
实现方式:先将内存一分为二,将有用的放一边没用的放一边,最后把没用的那边清除,释放内存【相信北漂的各位都搬过家,大多是这么干的吧】
适用场景:存活对象少的情况,适合Eden区
特点:对象的移动成本很高,对象移动了引用也要移动,空间浪费
3.3、标记压缩法
实现方式:整理的过程中将有用的压缩到头上【就是搬家的时候装麻袋么】,没用的释放空间
适用场景:对内存适用率要求高的场景,因为这种方式清理完成后,被使用的都是连续的空间,没用碎片
特点:移动对象有成本、也要扫描两次,效率偏低
4、常用的垃圾回收算法
4.1、Serial 年轻代单线程串行回收,在JDK诞生初期就有
4.2、为了提高效率,在Serial的的基础上诞生了PS,年轻代多线程并行回收
4.3、ParNew 是为了配合CMS诞生的一个并行回收
4.4、SerialOld (单线程老年代回收)
4.5、ParialOld (多线程老年代回收)
4.6、ConcurrentMarkSweep 老年代并发回收,工作线程和垃圾回收线程同时执行,大大降低了STW【Stop the world】的是时间
CMS问题比较多,所有到目前为止,没有一个版本的JDK默认使用CMS,只能手工指定,CMS既然是采用MarkSweep,就一定会有碎片化的问题,碎片到达了一定程度,CMS的老年代对象分配不下的时候,使用SerialOld进行老年代回收。
4.7、G1(STW 10ms) 使用算法:三色标记 + SATB
4.8、ZGC(STW 1ms) PK C++ 使用算法:ColoredPointers + LoadBarrier
4.9、Shenandoah 使用算法:ColoredPointers + WriteBarrier