HotSpot垃圾收集
一、收集算法
1、标记-清除算法(Mark-Sweep):
最基础的算法,分为两个阶段:
①标记:标记出所有需要回收的对象
②清除:标记完成后统一回收所有被标记的对象;
之所以说标记-清除算法是最基础的算法,是因为后面的算法都是基于这个算法而进行改进和完善的。
他的不足之处主要有两个:
①首先是标记和清除的过程效率都不是很高
②其次在标记-清除完之后,容易产生大量不连续的内存碎片,如果后续需要为大对象分配空间时,会因为找不到足够的连续内存空间而触发另一次收集动作;
2、复制算法(Coping):
在标记-清除的基础上,提高了效率。他将可用的内存空间划分为大小相等的两部分,每次只使用其中的一块空间,收集时将仍然存活的对象复制到另外一块内存空间中,然后将剩下的那个内存中的对象全部清理掉;这样的话,每次都是针对半个内存空间进行回收,存储对象时也是在完整的半个空间中进行操作,不会存在大量不连续的内存碎片等复杂情况;但是这个算法的代价是将存储对象的内存空间缩小了;
现在大部分的商业虚拟机都是通过复制算法来回收新生代的,根据IBM公司的研究表明:新生代对象98%都是“朝生夕死”的,因此根本不需要根据1:1的比例来划分内存空间,而是将内存空间划分为一块较大的Eden区和两块较小的Survivor区,每次只使用Eden区和一块Survivor区,在进行回收时,将Eden和From Survivor中不需要回收的对象一次性复制到另一块也就是To Survivor中,再清理掉Eden区和From Survivor区,这次回收中的To Survivor就是下次回收时的From Survivor区;HotSpot虚拟机默认Eden和Survivor的空间大小比例为8:1,因此新生代只有10%的空间会被浪费;
然而每一个项目的具体代码情况不同,并不能保证每次回收时都只有不超过新生代10%的对象存活,为了规避这种风险,需要依赖其他内存空间(此处指老年代)来进行分配担保,也就是说当To Survivor空间的内存不够存放本次回收时存活的对象时,这些对象将直接通过分配担保机制进入老年代;
3、标记-整理算法(Mark-Compact):
复制算法在标记-清除算法的基础上提高了些效率并且避免了大量不连续的内存碎片等不足之处,但是如果在回收中对象的存活率很高,那么每次回收时进行复制的对象将会较多,效率也会变低;并且,复制算法是需要舍弃一部分空间来进行复制操作的,同时还需要有其他内存空间来分配担保,所以老年代是无法使用复制算法的,那么就产生了标记-整理算法;
标记-整理算法的标记过程和标记-清除算法的标记算法相同,但是后续不是对标记的可回收对象直接进行清理,而是让所有存活的对象都向一端移动,然后清理掉端边界以外的内存;
4、分代收集算法(Generationl Collection):
现在大部分商业虚拟机的垃圾收集都是使用分带收集算法的;这种算法的核心思想是根据对象的生命周期将内存划分为几块,不同年龄的对象放在各自的内存区域内,一般是将堆内存划分为新生代和老年代:
①在新生代中,几乎每次垃圾收集时都有大量的对象死去,只有少量存活,因此比较适合使用复制算法,复制操作的成本低、效率高,所需“浪费”的空间也不会太大
②老年代中的对象几乎都是存活时间比较长久的对象,存活率高,也没有额外内存来为他进行分配担保,因此必须要使用标记-清除或者标记-整理算法来进行收集回收;
二、HotSpot算法实现
三、垃圾收集器
注:算法的执行和收集器有待后续添加;
本文内容皆为作者阅读《深入了解Java虚拟机》时的个人总结和个人复习;