判断对象生死的两者方法
-
引用计数法
每个对象添加一个引用计数器,有对象引用他,计数器加一,引用失效,计数器减1,互相引用导致不能被回收。
-
可达性分析
通过一系列被称为GC root的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程中走过的路径被称为引用链, 如果某个对象到GC root间没有任何引用链相连接,在有向图中表示GC root到这个对象不可达,此对象不可能再被使用。
GC Roots的对象包含:
-
在虚拟机栈中引用的对象,
-
方法区中类静态属性引用的变量,
-
方法区中常量引用的对象(如字符串常量池中的引用)
-
本地方法栈中JNI引用的对象
-
java虚拟机内部的引用,如基本数据类型对应的class对象,常驻异常对象,系统类加载器等
-
所有被同步锁(synchronized关键字)持有的对象
同时需要考虑针对某一区域进行垃圾收集时,需要将关联区域的对象一并加入GC roots
引用类型 自己举出对应的示例
-
强
最常见的引用类型,只要有强引用关系在,就不会被回收。
-
软
表示还有用但是非必须。
内存快要溢出时(已经回收过一次仍然濒临溢出),会二次回收只被软引用关联的对象。
-
弱
非必须对象,只能活到下一次回收前。
-
虚
幽灵引用,仅仅为了在对象被回收时接到系统通知,随时可能被回收。
public static void main(String[] args) {
ReferenceQueue queue=new ReferenceQueue();
Object obj=new Object();
SoftReference soft=new SoftReference(obj,queue);
WeakReference weak=new WeakReference(obj,queue);
PhantomReference pha=new PhantomReference(obj,queue);
}
finalize()方法:
对象被判定为不可达之后,还需要判断他有没有覆写finalize方法或者执行过此方法。
如有必要执行,则会放在一个队列中,通过一个虚拟机自动建立并且低调度优先级的Finalize线程去执行finalize方法(对象需要与引用链上任意一个对象建立关联才可自救)
任何一个对象的finalize()方法都只会被系统自动调用一次,如果对象面临 下一次回收,它的finalize()方法不会被再次执行。
建议不要使用,容易导致引用关系混乱,关闭资源完全可以使用finally。