o关于GC需要考虑的问题:
?哪些对象需要回收
?什么时候回收
?如何回收
哪些对象需要回收: 已经“死去”的对象需要被回收释放内存
首先,需要判断对象是否存活。
1.引用计数法 Reference Counting
给对象添加一个引用计数器,每当有一个reference变量指向该对象时,计数器加1, 当引用失效时,计数器减1,计数器为0时表示该对象不可能在被使用。
引用计数法实现简单,判定效率高,Java中没有使用该方法来管理内存是因为它很难解决对象之间相互循环引用的问题。
对象之间互相循环使用容易造成内存泄漏[内存泄漏]而浪费空间资源。
2.可达性分析法 GC Roots Treacing
通过一系列名为“GC Roots”的对象为起点向下搜索,搜索路径称为“引用链” reference chain,当一个对象节点到GC Roots之间不可达,则该对象“死亡”,可以被回收。
如上图所示,虽然对象4、5、6相互引用,但是他们与 GC Roots之间是不可达的,因此被判定为“死亡”对象可以回收。
为了描述这样一类对象(当内存空间足够时,这些对象可以保存,若即使GC后内存资源依然很紧张中,那么这些对象将会被抛弃回收),Java将引用分为四类:
1).强引用 Strong Reference : 类似“ Object obj = new Object()” 这样的称之为强引用,只要强引用还存在,该对象就不会被回收。
2).软引用 Soft Reference : 关联有用,但是非必需的对象。
对于软引用关联的对象,当内存不足时,会将这些对象列为回收范围进行第二次回收,如果这次回收后内存依然不足,会抛出内存溢出异常。
Java提供了SoftReference类来实现软引用。
3).弱引用 Weak Reference: 关联非必需对象,强度较软引用更弱一点。
弱引用关联对象智能生存到下一次GC发生的时间。当垃圾回收器工作时,无论内存是否够用,弱引用关联的对象都会被回收。
Java 提供了WeakReference类实现弱引用
4).虚引用 Phantom Reference:虚引用不会对对象的生命周期造成影响,也无法通过虚引用来获得一个对象实例。为对象设置虚引用的唯一目的就是希望在回收该对象时受到一个系统通知。
Java 提供了PhantomReference 类来实现虚引用。
在可达性分析法中,当一个对象被发现与GC Roots不通,这个对象并不会被立即处死,而是先对该对象进行标记,然后查看它是否重写了finalize()方法,如果有则将其移到一个名为的F-Queue队列之中,由一个由虚拟机自动创建的、低优先级的Finalizer线程触发执行。如果对象在finalize()中成功将自己与关联到引用链上,那么在第二次标记时该对象会被移出“即将回收”集合,否则,该对象将被彻底销毁。
这种自救方法只有一次,因为一个对象的finalize()最多只会被系统调用自动一次。