垃圾回收首先要分清jvm内存中什么是垃圾什么不是垃圾。jvm在识别垃圾时并不是使用通常认为的引用计数法,因为引用计数法无法解决两个对象之间的循环引用问题。为了解决循环引用问题,使用的是根节点遍历法,可以用图论中的不可达子图来理解。当从根节点出发进行遍历时,不可达的对象即认为是垃圾,是要进行回收的。
垃圾回收的方法通常有四类。
一、标记-清除法
这种方法分为两个阶段,首先标记jvm中的垃圾内存,然后对被标记为垃圾的内存对象进行统一回收。缺点是效率不高,容易产生大量的内存碎片,当需要较大的连续空间时无法申请到足够的内存。
二、标记-整理法
这种方法也分为两个阶段,首先也是标记垃圾对象,然后将内存中的存活对象向前移动覆盖掉被标记为垃圾的对象。这样每次整理后内存中前面都是存活对象,后面都是连续的可用内存空间。
三、复制法
把内存分为两块,使用时只适用其中的一块,当这块内存不够使用时,进行垃圾回收。回收时将现在使用的内存中的存活对象复制到另一块没有使用的内存上,完成后再把已使用的内存空间一次清理掉。缺点是内存使用效率低,当对象存活率较好时执行较多的复制操作,导致效率下降。所以现行的商用jvm中都不是按照1:1来分配内存的。
四、分代回收法
根据对象存活周期不同,将内存划分为几块,一般把java对分为新生代和老生代。新生代中有大量的对象死去,所以采用复制法进行垃圾回收。老生代中对象存活率较好,没有额外的空间对它们进行分配担保,就必须采用标记-清除法或标记-整理法。