Java虚拟机中的垃圾回收机制的是虚拟机的灵魂所在。
下面介绍下虚拟机中的主要回收算法。
引用计数法
实现:
对于实例化的一个对象O。只要有任何一个其他的对象引用O。O的引用计数器就加一。当引用失效的情况下,引用计数器减一。
优点:
实现简单
缺点:
(1)当出现循环引用的话无法处理。(例如A引用O,O也引用A)
(2)每次引用计数器的加一减一操作会对系统的性能有一定的影响(实际项
目中当大量的对象被创建,并且互相引用时,引用计数器的加减操作会变得不能忽视)
标记清除法
实现:
标记清除算法分为标记和清除两个阶段。
标记阶段的时候通过根节点搜索可达对象进行标记。
清除阶段清除所有不可达对象。
(根节点是指在程序中可以直接访问的对象,一般为栈中的本地变量和静态变量)
缺点:
回收后的空间是不连续的,不连续的空间工作效率要低于连续的空间。
标记压缩法
实现:
标记清除算法的改进,在标记后将所有的存活对象压缩到内存的一段,然后将边界外的空间进行清理。
优点:
相比较于标记清除算法, 回收后的内存空间连续。
相比较于复制算法,不需两块相同的空间,压缩实际的使用空间大小。
适用性:
适用于老年代。
老年代存活对象占大多数,垃圾对象占少数。
复制算法
实现:
将原有的内存空间划分为相同大小的空间。
1.每次只使用其中一块。
2.在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存中。之后清除正在使用的内存中所有的对象。
3.交换两个内存的角色。
优点:
确保了回收后的内存空间没有碎片
缺点:
实际可用空间只有系统最大内存的一半。压缩的可用内存空间。
适用性:
适用于新生代的垃圾回收。
新生代存活对象少,垃圾对象多。复制存活对象的成本低。
分代算法
实现:
将总的内存空间分为新生代,老年代,不同的代采用不同的算法
分区算法
实现:
将堆空间分为连续的不同小区间,每个小区间独立GC。每次GC时仅对需要GC的空间进行GC。减少一次GC时候的stop-the-world的时间。
(可以参考减少锁粒度的性能优化思想,实际上也是减少GC粒度)