保守式GC
保守式GC指“不能识别指针和非指针的GC”。
- 不明确的根,寄存器、调用栈。全局变量空间等属于GC root,这些GC均不能识别出是指针还是非指针。
- 指针的识别,在不明确的根的条件下可以已某种程度的精度来识别指针。
- 是否被正确对其
- 是否指向堆
- 是否指向对象的头
必须同时这三个基本的检查项目才可能是指针
- 不明确的根很可能出现数值但是同时满足以上三个条件产生"貌似指针的非指针(false point)",此时GC采取一种保守的态度,把所有可疑的引用均当作指针,因此称作保守式GC。
- 有点在于容易编写语言处理程序。
- 缺点则是识别指针的成本、错误识别指针导致垃圾变成存活对象和不能使用复制算法等移动对象的GC算法。
准确式GC
- 正确的根,可以直接识别出是指针还是非指针,都需要语言处理程序加工,即为准确式GC(Exact GC)
- 打标签,将不明确的根的所有非指针与指针区分开。32位系统的指针是4的倍数,低2位一定是0,因此可以让非指针左移一位,而后将最后一位置1,如果溢出则换一个大的数据类型。
- 不把寄存器和栈等当作根,而由处理程序来创建根。
- 优点在于不存在指针不明确,可以使用复制移动算法。
- 缺点则是需要语言处理程序对GC做支持,而且打标签等方式需要消耗资源与性能。
改进
间接引用
针对保守式GC不能使用复制算法
- 保守式GC不能使用复制算法原因在于当某个根为false point时,对其指定的对象进行复制时将修改该根,但是该根其实质应该是具体的数值,这将导致程序异常。
- 通过句柄(handle)来间接处理对象,所有的根只指向对象句柄,句柄再指向具体的对象,当移动对象时不需要改变根,只需要改变句柄的值。
- 优点:保守式GC可以使用复制算法
- 缺点:访问一次对象需要访问内存两次。
黑名单
针对保守式GC指针识别错误
- 创建“需要注意 的地址的名单”,该黑名单里记录着“不明确的根内的非指针,其指向的是有可能被分配对象的地址”。
- 面向黑名单内的地址分配小对象和没有子对象的对象可以降低由损失。