一、什么是垃圾回收
垃圾回收(Garbage Collection,简称GC)也称垃圾收集,Java程序会不定时的被唤起检查是否有不再被使用的对象,并释放它们占用的内存空间。
垃圾回收就需要完成三件事情:①哪些对象的内存需要回收?②什么时候回收?③采用什么办法回收?
1. 如何判断对象是否已死
这里判断对象已死,说明对象已经没有作用了,需要把它们的内存释放出来,以便于后面程序新产生的对象使用。一般判断对象是否已死有两种方法:
1)引用计数法
给每个创建的对象添加一个引用计数器,每当此对象被某个地方引用时,计数值+1,引用失效时-1,所以当计数值为0时表示对象已经不能被使用了。
引用计数器算法大多数情况下是个比较不错的算法,简单直接,判断效率高,也有一些著名的应用案例但是对于Java虚拟机来说,并不是一个好的选择,因为它很难解决对象直接相互循环引用的问题。
2)可达性分析算法
在主流的商用程序语言如Java、C#等,都是通过可达性分析(Reachability Analysis) 来判断对象是否存活的。此算法的基本思路就是通过一系列的”GC Roots“的对象作为起点,从起点开始向下搜索到对象的路径。搜索经过的路径称为引用链(Reference Chain),当一个对象到任何GC Roots 都没有引用链时,则表名对象不可达,即该对象是不可用的。
可用作为GC Root 的对象有哪些?
- Java虚拟机栈(栈帧中的局部变量表)中的引用所引用的对象。
- 方法区中类静态属性所引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈JNI(Native方法)引用的对象
- Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointException、OutOfMemoryError)
- 所有被同步锁(synchronized关键字)持有的对象
- 反映Java虚拟机内部情况的JMXBean、JVMTI(JVM Tool Interface)中注册的回调、本地代码缓存等
2.分代回收
根据对象的生命周期将内存划分,然后进行分区管理。当前商业虚拟机的垃圾收集器,大多都遵循了“分代收集”(Generational Collection)的理论进行设计。分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,它建立在两个分代假说之上:
- 弱分代假说:绝大多数对象都是朝生夕灭的。意思就是绝大部分对象存活时间都不长。</