JVM垃圾回收算法
一、什么样的对象是垃圾?
在JVM(Java虚拟机)中,被成为“垃圾”的对象是指那些不再被应用程序使用,即没有任何引用指向它们,且在未来也不会被使用的对象。JVM通过垃圾回收机制来自动识别和回收这些对象,以释放内存空间供其他对象使用。
二、如何判断垃圾?
1、引用计数算法
对每个对象保存一个整型的引用计数器属性,用于记录对象被引用的情况。
如上图所示,当对象被引用时,计数器进行“+1”操作;反之,则“-1”,因而引用计数算法的判定效率高,且回收没有延迟性;但正因如此,每次赋值都伴随加减法的操作,增加了实践的开销,且无法处理循环引用的问题。
循环引用通常指的是两个或多个对象相互引用对方,导致它们的引用计数增加,从而使得这些对象无法被正常释放,引发内存泄漏问题。例如,如果对象A引用对象B的强引用,同时对象B也持有对象A的强引用,那么A和B的引用计数都会为1,它们都无法被释放,这就构成了循环引用。
2、可达性分析算法
通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是存活的,不可达的对象可被回收。
上图中,对象A,B,C都是可达的,而对象D,E,F不可达。
可作为GC Roots的对象有哪些?
- 栈中引用的对象
- 类静态属性引用的对象
- 常量引用的对象
- Native本地方法引用的对象
三、如何回收垃圾?
标记-清除
将存活的对象进行标记,然后清理未被标记的对象,但会不断产生碎片,使得内存使用量越来越低。
复制法
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。由于将内存分为两块,所以内存的空间会浪费一倍。
标记-整理
让所有存活的对象都像一端移动,然后直接清理掉端边界以外的内存