Java垃圾收集算法
==============================
上一个博客中,学习了一下Java中的对象是否存活,对于存活的对象可以继续使用,但是对于回收以释放空间的对象,需要虚拟机来回收资源。回收资源就需要有回收的算法,这次主要学习一虚拟机收集垃圾的算法,本次的学习由于能力有限只能理解一下算法的思想,具体实现没有深入了解。
标记-清除算法
这是虚拟机中最基础的收集算法了,他的实现对应了他的名字分为了“标记”和“清除”两个过程。首先虚拟机会标记出所有的需要回收的对象,标记完成后统一回收,关于对象的标记可以参考上一篇《Java对象的生与死》,简单介绍了关于Java对象是否存活的标记过程。这种算法实现比较简单,但是它的效率和空间成了他的瓶颈问题。标记和清除的效率都不高,对于空间来说,那些已被标记的对象不一定是连续分布在内存空间中的。所以回收之后,就会在内存中造成内存碎片,而且当程序运行过程中需要给较大对象分配空间时,就不得不再执行一次垃圾回收以寻找空间。
复制算法
复制算法首先是将内存均分为两块(A、B),使用时先在A上为对象分配内存,当需要执行垃圾回收时,就将A上还存活的所有对象复制到B上,然后将A全部清除回收。这样就每次都只对半边内存进行回收,也不会有内存碎片存在,算法简单,效率也比较高。但是将内存缩小为原来的一半来使用,代价稍微有点高了。
标记-整理算法
对于复制收集算法,如果有一些对象的生命力比较旺盛,存活时间比较长,采用复制算法的时候就需要多次将其复制,这样就会降低效率,并且内存本来就比较小比较珍贵,将其降低一半来使用,是不合理的。如果不想浪费50%的空间,就得有空间斤西瓜分配担保。以应对长期存活的对象。针对老年代的这种特点就需要标记-整理算法了。“标记”过程依然和前面的“标记-清除”算法一样。“整理”的意思是,将所有的存活对象移动到一起,然后从存活对象的末尾开始清楚,将剩下的内存全部回收。这样得到的内存就是连续的。
分代收集算法
这种算法是将前面的几种算法根据对象是新生代还是老年代来分配使用的。根据每个年代的不同特点选择不同的收集算法,提高效率。对于新生代:存活的时间比较短,每次都有大量的对象死亡,只有少量存活,那就选用复制算法,对象较少复制的成本也不高(这时用来复制的内存区域的划分可以是其他的比例,不一定为1:1);对于老年代:对象的存活时间都比较长,也没有额外的空间进行担保,这时采用复制算法效率就太低了,需要采用“标记-清楚”或者“标记-整理”算法。