java垃圾收集算法介绍

垃圾收集是java中相当重要的一部分,大部分人都把这项技术当作java语言的半生产物。事实上,GC的历史比java久远。本篇文章主要介绍java中的垃圾回收算法,并且由于垃圾收集算法设计大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同,所以只是简单介绍。

标记-清除算法

他是java中最基础的收集算法,如同它的名字一样,孙阿法分为“标记”和“清除”两个阶段,首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。之所以说他是最基础的收集算法是因为后续的收集算法都是基于何种思路并对其不足进行改进而以。

标记-清除算法它的不足有两个:1、效率问题,标记和清除两个过程的效率都不高;2、空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。

标记-清除算法执行过程如下图:

复制算法

复制算法主要为了解决效率问题,他将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活着的对象复制到另外一块上,然后再把已使用过的内存哦那个贱一次清理掉。这样使得每次都是堆整个半区进行内存回收,内存分配时也就不考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高校。但是这种算法的代价是将内存缩小为原来的一半,代价有点高。复制算法的执行过程如下:

目前商业虚拟机都是采用这种算法来回收新生代,IBM公司的专门研究表明,新生代的对象98%是朝生夕死的,所以并不需要按照1:1的比列来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性的复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。

虚拟机默认Eden和Survivor的比例是8:1,也就是每次新生代中可用内存为整个新生代容量的90%,只有10%会被浪费。当然98%的可回收对象只是一般场景下的数据,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(这里指的是老年代)进行分配担保。

标记-整理算法

复制收集算法在对象存活率较高是就要进行较多的复制操作,效率将会变低。更关键的如果不想浪费空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都存活的极端情况,所以在老年代一般不能直接使用这种算法。

根据老年代的特征,提出了另外一种“标记-整理”算法,标记过程仍然于“标记-清除”算法一样,但后续步骤不是直接堆可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存,清理步骤如下如:

附上java对象存活算法 java对象存活算法

原文链接:https://www.jianshu.com/p/b992a08bbd45 如有侵权请联系作者删除
 

发布了10 篇原创文章 · 获赞 0 · 访问量 4425

猜你喜欢

转载自blog.csdn.net/xiaohuihui501/article/details/103934270