1.援用计数法
2.可达性剖析算法
3.谈一谈GCRoot
在堆外面寄存着JAVA世界中简直所有的对象实例,垃圾收集器在对堆对象进行回收以前,第一件事件就是要确定这些对象之中哪些还“存活”着,哪些曾经“死去”。
1.援用计数法
援用计数法就是一种断定该对象是否为垃圾对象的办法,它是这么做的:在每个对象中增加一个援用计数器,当有中央援用这个对象的时候,援用计数器就+1,当援用生效的时候,计数器的值就-1。任何时刻计数器为0的对象就是不可能再被应用的。
这种办法是一个不错的算法,而且非常容易实现,然而JAVA虚拟机却没有选用援用计数法来治理内存,其中最次要的起因是因为它很难解决对象之间互相循环援用的问题。
举个简略的例子
ReferenceCountingDemo obj1 = new ReferenceCountingDemo(); ReferenceCountingDemo obj2 = new ReferenceCountingDemo(); obj1.instance = obj2; obj2.instance = obj1; obj1 = null; obj2 = null;
此时咱们能够看出,obj1和obj2曾经没有援用对象了,然而他们的实例属性instance还援用这对象,这种状况下,它们各自的计数器的值还是1,因而,这种办法很难解决对象之前循环援用的问题。
2.可达性剖析算法
目前的JAVA虚拟机是应用可达性剖析算法来断定对象是否存活的,这个算法的基本思路就是通过一系列被称为(GCRoot)的对象作为起始点(什么是GCRoot咱们下文再谈),从这些节点开始向下搜寻,搜寻所走过的门路成为援用链,,当一个对象没有任何援用链相连,则证实此对象是不可用的,回收。
3.谈一谈GCRoot
上文咱们提到过可达性剖析算法通过GCRoot开始搜寻,那么有哪些对象能够当做GCRoot?
a. java虚拟机栈中的援用的对象。
b.办法区中的类动态属性援用的对象。 (个别指被static润饰的对象,加载类的时候就加载到内存中。)
c.办法区中的常量援用的对象。
d.本地办法栈中的JNI(native办法)援用的对象
接下来咱们就对上述四种状况做一个剖析:
a. java虚拟机栈中的援用的对象。
咱们都晓得,java虚拟机在调用办法的时候都会创立一个相应的栈帧,栈帧中蕴含了这个办法外部应用的所有对象的援用,一旦办法执行完结之后,这些长期对象援用也就不复存在了,这些对象就会被垃圾收集器给回收。
b.办法区中的类动态属性援用的对象。 (个别指被static润饰的对象,加载类的时候就加载到内存中。)
这个没什么好解释的, 就是被static润饰的对象,多用于单例模式的写法。
c.办法区中的常量援用的对象。
也就是被final润饰的对象。
d.本地办法栈中的JNI(native办法)援用的对象
最初,真的要宣告对象死亡须要通过两个过程
1.可达性剖析后没有发现援用链
2.查看对象是否有finalize办法,如果有重写且在办法内实现自救(如再建设援用),还是能够抢救一下。