您的位置:首页 > 编程语言 > Java开发

深入理解Java虚拟机(2) - 根搜索算法

2017-02-21 19:47 295 查看
这个系列文章是对《深入理解Java虚拟机》一书的笔记及个人理解

垃圾收集(Garbage Collection,GC)需要完成三件事件

1、哪些内存需要回收?

2、什么时候回收?

3、如何回收?

Java虚拟机要进行GC,首先要确定哪些内存需要回收,但是GC时,Java程序依然是在运行当中,所以,如果将程序需要的对象回收了,就会造成程序出错。那么,怎么在Java堆中的众多对象中找出哪些是可以被回收的,哪些是不能被回收的?

引用计数算法

这是教科书版本:给对象添加一个引用计数器,当有一个地方引用它时,计数器值加1,当引用失效时,计数器值减1,当计算器值为0时,则表示该对象不可能再被使用,可以被回收了。

简单好理解,判定效率高。但Java语言并没有使用这个算法来管理内存,其中最主要原因是它很难解决对象之间的相互循环引用的问题。

前面讲的就像是一个单相思,A暗恋B,A中产生了一个B的引用,B的引用数加1,哪天A移情别恋了,A中对B的引用就被设置空,于是B的引用数就减1。但是,A把暗恋搞成了相恋,情况就会变得不一样,B中也会产生一个A的引用,于是A的引用数加1,这时,他们厌倦了这个红尘俗世,找了个世外桃源隐居起来,没有任何外界的人可以找到他们,但因为他们互相之间的关系,他们始终会存在至少一个引用数,但他们作为一个整体已经是永远没办法找到了。

代码示范:

package demo4;

public class ReferenceCountingGc {

public Object instance = null;

private static final int _1MB = 1024 * 1024;

private byte[] bigSize = new byte[2 * _1MB];

public static void testGC() {
ReferenceCountingGc objA = new ReferenceCountingGc();
ReferenceCountingGc objB = new ReferenceCountingGc();
objA.instance = objB;
objB.instance = objA;

objA = null;
objB = null;

System.gc();
}
}


根搜索算法

这个算法的基本思路是:通过一系列名为”GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(reference chain),当一个对象到”GC Roots”没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

如下图所示,对象 object5、object6、object7虽然互有关联,但是它们到达GC Roots是不可达的,所以它们会被判定为是可回收的对象



在Java语言里,可作为GC Roots的对象包括下面几种

1、虚拟机栈中的引用的对象

2、方法区中的类静态属性引用的对象

3、方法区中常量引用的对象

4、本地方法栈中JNI(即一般说的Native方法)的引用的对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息