在谈Java垃圾回收机制前,先来看下其他一些系统的垃圾回收机制,常见的有引用计数技术—即为每个对象都设置一个引用计数器,有引用时加1,当有引用离开作用于或被设置为null时,引用减1.当引用减少为0时,回收对象内存。 这种回收机制有许多弊端,低效率,而且无法解决无法解决对象交付引用的回收问题,比如对象间出现循环引用的情况(对象引用数都不为0,但其实应该被回收)。
与上述垃圾回收机制不同,Java采用的是更为高效的回收机制,不同Java虚拟机下的回收机制也不一样,常见的有以下几种:
一种是“停止-复制”模式,停止当前运行程序,从当前堆栈或静态去区的引用中遍历所有对象,将所有存活的对象从堆中复制到另一个堆,没有被复制的就是垃圾,将被回收,另外在复制的过程中也可以对存活的对象进行重排列,使其更紧凑,提高程序运行效率。 这种方式的弊端就是对内存开销较大,需要再复制出一个堆,即使是当前内存中需要回收的对象很少。
另一种就是“标记-清理”模式,即从当前堆栈或静态区的引用中遍历所有对象,每当找个一个活的对象,给其打上一个标记,遍历完成后,没有标记的对象将被回收,这种机制就可以在一定程度上解决上述“停止-复制”模式带来的弊端。
除此以外,还有一种结合了上述两种模式的自适应模式,内存分配时会以较大的块为单位,每个块设置代数,大的对象单独占据一个块,复制时大对象的块不会复制,但其代数增加,只会将小对象从块中复制到另一个块,减少了完全采用“停止-复制”模式带来的消耗,另外在程序内存较稳定时,采用“标记-清理”模式,碎片较多时改用“停止-复制”模式。