Java语言的一大特点就是可以进行自动垃圾回收处理,而无需开发人员过于关注系统资源的释放情况,垃圾回收机制要处理的基本问题有3个,1、哪些对象需要回收,2、何时回收这些对象,3、如何回收这些对象。下面是几种常见的垃圾回收算法及其核心思想:
1、引用计数发:这是最古老也是最经典的垃圾收集方法,其算法很简单,对于一个对象A,只要任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1,只要对象A的引用计数器的值为0,则对象A就不在被使用,可以作为垃圾清除。这种方法虽然简单,但是无法解决循环引用的问题,就是两个对象相互引用,而没有第三方引用,本来AB都改被清除的,反而无法被清除句造成了内存泄露,所以这种方法现在是不使用的。
2、标记-清除算法:这是现代垃圾回收算法的基础,标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象,未被标记的对象就是未被引用的垃圾对象,然后再清除阶段,清除所有未被标记的对象。这个思想的意思是,在程序的起点开始就是一个根节点,随着程序的运行就会引用不同的节点,被引用的做标记,未被引用的做清除标记,做清除标记的作为垃圾回收。这种算法的缺点就是会产生空间碎片。
3、复制算法:这是一种高效的回收算法,其核心思想是:将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存活的对象复制到未使用的内存块中,之后,清除正在使用的内存块的所有对象,然后再交换两个内存的角色,这样就完成了垃圾回收。其缺点是当内存中大部分都是存活对象,那么这种算法都是在做无用功。
4、标记-压缩算法:这是一种老年代的回收算法,在标记-清除算法做了改进,也是从根节点开始,对所有对象做一次标记,对标记清除的对象不是简单的清除,而是先把存活对象压缩到内存的一端,确定好边界之后,再把所有的标记清除的对象全部删除,这样就避免了碎片的产生,同时又不需要频繁交换空间。
5、增量算法:在大部分垃圾回收过程中,一旦开始回收,应用程序所有线程都处在挂起状态,时间很长的情况下,会影响用户体验以及性能稳定。增量的算法就是:如果一次性将所有垃圾进行处理,需要造成系统长时间的停顿,那么可以让垃圾回收线程与程序线程交替进行,每次只回收一片区域,接着再切换到程序进程,缺点就是:线程之间的不停切换会影响整体成本的升高。
6、分代:前面的算法都各有自己的优缺点,分代的基本思想就是:它将内存区间根据对象的特点分为几块,根据每块内存区间的特点,使用不同的算法,从而提高垃圾回收效率。一般内存区域分为老生代和新生代,新建的对象建在新生代,常用的对象建在老生代,新生代用复制算法,老生代用标记-压缩算法。这样两边的效率最高,这是目前最常用的垃圾回收算法。