Java虚拟机知识整理——垃圾清理

时间:2023-01-02 22:54:05

经过一定的判断后,虚拟机认定一些对象是垃圾,这也只是判断而已。需要一个“清洁工”去把已经是垃圾的对象进行回收。回收的方法很多,这里说的是几种算法思想。

标记——清除算法

如同算法的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后同意回收所有被标记的对象,它的标记过程就是之前一篇中所说的判断对象是否是垃圾的过程。
这个算法是最基础的手机算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到大。它的主要不足有两个:一是效率问题,标记和清楚两个过程的效率都不高;另一个是空间问题,标记清楚后会产生大量不连续的内存碎片,内存碎片会单只以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾手机动作。

复制算法

为了解决效率问题,复制算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活这的对象复制到另一块上面,再把之前使用过的空间一次性清理掉。
这样使得每次都是对整个搬去进行内存回收,内存分配时也不用考虑内存碎片等复杂情况,值要移动堆顶指针,按顺序分配内存即可。实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一般,未免太高了一点。

标记——整理算法

算法标记,清理的时候让所有存活的对象都向一段移动,然后直接清理掉边界以外的内存。
这个算法解决了内存空间的问题,但是执行的时间会变得更多,比较适合频率比较低的垃圾收集。

分代收集算法

当前商业虚拟机的垃圾手机都采用“分代收集”算法,这种算法没有新的算法思想,只是根据对象存活周期的不同将内存划分为几块,一般是把Java堆分为新生代和老年带,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都会发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须采用“标记——清理”或者“标记——整理”算法来进行回收。

高技巧的“清洁工”工作

Java的有专门负责清理的线程来执行垃圾标记和收集的工作,可以看做是Java的“清洁工”他的工作比一般的清洁工工作难度要高的多,必须要运用实现了这些算法思想的算法来执行。