JVM - HotSpot

标记清除法

标记出不需要回收的对象,清除没有被标记的对象,它是最基础的收集算法,后续的算法都是对其的不足进行改进。

标记后会产生大量不连续的内存碎片。

标记复制法

将操作区域分为两块,每次只使用一块,当内存用尽会将存活对象复制到另一块区域,然后把它清理回收,减少回收区域。

标记整理法

标记出不需要回收的对象,然后往前移动,然后清理掉尾部的对象。

分代收集法(当前主流

划分分新生代跟老年代(为了更好的回收内存),新生代又分 Eden,From Survivor,To Survivor,根据每个区域不同的情况提供不同的算法。

每个对象都会有个年龄计数器,首先会在Eden区域先分配,当没有空间时,虚拟机开始GC,如果对象还存活,年龄就会+1,同时 Survivor 区域能容纳下的话,就晋升到 Survivor 区域,当年龄大于15会晋升到老年代;

如果分配空间时,检测新生代的剩余空间比老年代的大,就会触发全局回收(full gc),System.gc() 也是触发的 full gc。

新生代中每次执行都会有大量对象回收,所以为了提高效率分配了标记复制法,而老年代存活率较高,所以分配了标记清除法标记整理法

引用计数法

每个对象会有个计数器,每持有一个引用计数+1,引用失效,计数器-1,计数为0表示不在被使用。

引用计数法存在缺陷,无法解决循环引用问题(A,B两个对象互相引用),导致引用计数器不为0无法回收。

可达性分析法

生成一个叫 GC Roots 的对象作为起点,向下搜索,搜索路径叫引用链,无法通过引用链到达 GC Roots 起点的都是可能被回收对象;

GC Roots一般是同步锁持有对象,静态属性引用对象,常量引用对象等;

不可达对象会被标记一次,然后会判断是否有必要回收(是否调用 object 的 finalize 回收方法),如果被判定为有必要回收,会再次标记,然后执行回收。

finalize 方法官方已经不推荐,因为它是不可控的,无法立即执行gc。

 

引用

强引用:不会回收,直接抛异常;

软引用:空间不足时回收;

弱引用:被发现了就会被回收;

虚引用:随时可能会回收。

 

收集器

Serial(串行)收集器

单线程收集器,也是基础收集器,只会使用一条垃圾收集线程去完成垃圾收集工作,收集工作的时候必须暂停其他所有的工作线程,直到结束。

用户体验不佳,但是简单高效。

ParNew 收集器

多线程收集器,基于Serial收集器。

Parallel Scavenge 收集器

多线程收集器,提供了很多参数供用户找到最合适的停顿时间,适合自适应调节策略,也是JDK1.8的默认收集器。

CMS 收集器

单线程收集器,真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。

posted on 2022-03-18 21:46  翻滚的咸鱼  阅读(252)  评论(0编辑  收藏  举报