实战java虚拟机(二)——垃圾回收算法

前言


垃圾回收是Java体系最重要的组成部分之一,和C/C++不同,Java虚拟机提供了全自动的内存管理方案,尽量减少了我们在内存资源管理方面的工作量,但是这套方案也并不完美,因此我们也需要深入学习垃圾回收的算法,在工作中遇到内存溢出等问题时也容易更快找到问题所在

 

一、引用计数法


引用计数法是最古老的垃圾收集算法,它的实现非常简单,只需要为每个对象配备一个整型计数器即可,当对象被引用时,计数器+1,引用失效时计数器-1.

显而易见,这种方式有着两个非常严重的问题:

1.无法处理循环引用,如果对象A,B相互引用,且不存在第三个对象引用了A或B,按道理AB两个对象是垃圾对象需要被回收,但是AB之间的相互引用导致计数器永远不为0,无法被回收

2.在每次引用产生和消除的时候,需要额外的操作对计数器做加减法,对性能会存在一定影响

因此,Java虚拟机没有选择此算法作为回收算法

 

二、标记清除法


标记清除法是现代垃圾回收算法的思想基础,它分为两个阶段:标记阶段和清除阶段。一种简单的具体实现方法如下

在标记阶段,通过根节点标记所有从根节点开始的可达对象,在清除阶段,清除所有未被标记的对象。

显然,这种方式很容易产生空间碎片,回收后的空间不连续,后续空间分配时,尤其是大对象的分配,会导致效率大大降低,这也是这种算法的最大缺点。

 

三、复制算法


该算法的核心思想是:将原有的内存空间分为两块,每次只使用其中一块,进行垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,再清楚正在使用的内存块中的对象,完成垃圾回收。如果系统中的垃圾对象较多,算法需要复制的存活对象数量就较少,因此,在真正需要垃圾回收的时候,复制算法的效率是很高的,而且对象是统一复制到新的内存空间,确保回收后的内存空间是没有碎片的,但是这么做的代价也是很高的,系统的内存使用率将最高只有50%

 

四、标记压缩法


标记压缩法是一种老年代的回收算法,它在标记清除法上做了一些优化。与标记清除法相同,它有标记和清除阶段,不同的是,它不是简单的标记存活对象,而是将存活对象压缩到内存的一端,然后清理边界外的所有空间,这种方式既可以避免了碎片的产生,对内存的利用率也较高。

 

五、分代算法


分代算法基于生命区间长短划分成两个部分,根据每块内存区间的特点使用不同的算法,提高垃圾回收的效率。一般在新生代的是复制算法,老年代中是标记压缩/标记清除法。

 

六、分区算法


 

分区算法是将整个堆空间划分成连续不同的小空间,每个小区间独立使用回收

 

posted @ 2019-09-12 14:48  一秋复一秋  阅读(234)  评论(0编辑  收藏  举报