垃圾回收的第一要点就是垃圾分类。
上海垃圾回收分类指南.jpg
垃圾分类.jpg
为什么要学习 GC ?
1.为了面试装B。
2.了解使用不同 GC算法 对编程语言的影响。
3.熟悉内存空间的用法,辅助编写更优质的代码。
总之好处有很多,我就不再列举了。
常用的垃圾回收算法
引用计数法
在引用计数法中,每个对象都会有自己被引用的数值,当数值为0时变为垃圾等待回收。
优点:
减少了垃圾回收暂停时间。
不从GC Root开始查找。
缺点:
计数器工作繁琐。
计数器占用空间较大。
循环引用无法回收。
可达性分析法
可达对象表示从GC Root开始直接或间接引用到的对象。不可达对象则会等待GC将其回收。
GC Root.png
GC Root(以Java为例):
由系统类加载器加载的对象
活着的线程
正在被调用的方法中的局部变量或参数
全局JNI引用与JNI方法中的变量或参数
GC基本是对堆内存的操作,GC Root属于堆中的对象,但GC Root却是由堆之外的虚拟机栈、本地方法栈、方法区中引用的对象决定的。
标记-清除(Mark-Sweep)
标记-清除算法基于可达性分析把所有可达对象进行标记,然后统一清除未标记不可达对象。
标记-清除.png
由图中可以看出标记-清除算法会带来内存碎片化的问题,使得内存空间利用率越来越低。
优化:
多空闲链表法:用一个数组来分类存放不同空间占用的链表,比如数组[0]只存放占用2个字节的数据,数组[1]只存放3个字节的数据,便于搜索同大小类型的数据。
位图标记法:将标记位用独立于对象的“位图表格”进行存储,可以与写时复制技术兼容,同时可以加快消除标志位的速度。
BiBOP(Big Bag Of Pages):将堆提前分割为固定大小的空间,使每个空间只能配置同样大小的数据。
延迟清除法:顾名思义,延迟清除。因为每次清除都会遍历堆,消耗较大,所以最好降低清除次数。
复制算法
复制算法将空间分为大小一致的From空间与To空间,当From空间被占满后会将活着的对象全部复制到To空间,然后把From与To空间互换。
复制.png
优点:
效率高(耗时少、分配空间快、回收快)
空间利用率高
缺点:
空间占用大
递归调用复制函数容易栈溢出
优化:
多空间复制法(权衡From与To空间比例)例:2:复制算法 8:标记-清除算法
Cheney的GC复制算法
近似深度优先搜索优化CheneyGC复制算法
标记-压缩算法(标记-整理算法)
标记-压缩中的标记与标记-清除是完全相同的,接下来进行数次压缩将活动对象重新排列。
压缩.png
压缩主要就是将分散的活动对象靠近。
优点:
解决碎片化
提高利用率
缺点:
压缩需要频繁移动指针,成本高
优化:
Two-Finger算法将同等大小的活动对象补充到空闲空间。(制约条件:必须将所有对象整理成大小一致)
表格算法
ImmixGC算法
分代回收
将垃圾分为不同的几代,针对不同的代使用不同的GC算法。
常见的分类就像新生代(minor GC)与老年代(major GC),主要对新生代进行回收,减少对老年代的回收次数。
分代回收.png
优点:
因地制宜的方式使空间利用率最大化。
缺点:
不适用于生命周期长的新生对象。
优化:
多代分类垃圾回收(降低对象活到老年代的机会)
列车垃圾回收
增量式垃圾回收
增量收回是为了将在执行垃圾回收时STW(Stop-The-World)状态进行分割,每次只回收一部分空间,减少对正在执行的工作进行过久的阻塞,但是频繁切换上下文的消耗会造成总体成本的增加。
网友评论