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方法,如果有重写且在方法内完成自救(如再建立引用),还是可以抢救一下。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。