目录
- 1. 如何判断对象可以回收
- 1-1. 引用计数法
- 1-2. 可达性分析算法
- 1-3. 四种引用
- 强引用
- 软引用
- 弱引用
- 虚引用
- 终结器引用
- 2. 垃圾回收算法
- 3. 分代垃圾回收
- 4. 垃圾回收器
- 5. 垃圾回收调优
1. 如何判断对象可以回收
1-1. 引用计数法
引用计数法
- 只要一个对象被其他变量所引用,那么就让这个对象的计数
+1
- 如果其他变量不再引用,让这个对象的计数
-1
- 让这个对象的引用技术为
0
时,则说明没有变量引用了,就可以作为一个垃圾进行回收
引用计数法弊端
- 循环引用问题,A对象与B对象循环引用,他们的引用计数始终为1,不能作为一个垃圾进行回收
- 出现内存泄漏
1-2. 可达性分析算法
根对象:一些肯定不能作为垃圾的对象
可达性分析算法
-
在垃圾回收之前,会对堆内存所有的对象进行扫描
-
查看每一个对象是不是被
根对象直接或间接引用
-
如果是,则不能被垃圾回收
-
如果不是,则可以被垃圾回收
-
Java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
-
扫描堆中的对象,看是否能够沿着GC Root对象
(堆中对象)
为起点的引用链找到该对象(栈中对象
),找不到,表示堆中对象
可以回收 -
哪些对象可以作为GC Root
- 活动线程中局部变量
所引用的堆中对象
可以作为根对象
- 活动线程中局部变量
1-3. 四种引用
实线代表强引用
平时用的引用都是强引用
,例如:赋值运算
强引用
- 所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收。
软引用
- 只有【软引用】引用该对象时,在垃圾回收后,内存仍不足 则会回收软引用对象
- 可以配合【引用队列】来释放软引用自身,因为软引用自身也占用内存
★应用场景
- 非核心业务资源(比如:图片)被强引用特别多时,有可能报OOM异常,因为强引用是不会被回收的,内存满直接抛异常
- 那么就可以用【软引用】来指向这些资源,当内存不足时,回收这些资源。
- 以后如果再使用图片资源,重新读取一遍。
弱引用
- 只有【弱引用】引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
- 可以配合【引用队列】来释放弱引用自身,因为弱引用自身也占用内存
虚引用
- 必须配合【引用队列】使用
- 例如
ByteBuffer
对象不再【强引用】时,ByteBuffer
对象本身可以被垃圾回收,但是占用的直接内存
是属于操作系统的,无法被回收。 - 那么就可以将【虚引用】放入【引用队列】, 由
Reference Handler
线程调用虚引用相关方法释放【直接内存】 - 总结:【虚引用】引用的对象被垃圾回收时,【虚引用】被放入【引用队列】,从而由一个线程可以调用【虚引用】的方法。
终结器引用
Object
类中有finallize()
方法- 当一个类重写了
Object
类中有finallize()
方法,并且该对象没有被【强引用】时,就可以进行垃圾回收 - 第一次垃圾回收时,将【终结器引用】放入【引用队列】,并且由一个优先级很低的Finalizer线程去寻找【终结器引用】的对象,找到后执行该对象的
finallize()
方法。 - 直到第二次垃圾回收时,才将该对象进行垃圾回收。