先来说明一个什么情况下Java对象被判定为垃圾?
当没有被其他对象引用情况下该对象就是没有用的。
判断Java对象为垃圾的算法有哪些?
- 引用计数法
- 可达性分析算法
引用计数法
通过判断对象的引用数量来决定对象是否可以被回收;每个对象实例都有一个引用计数器,被引用加一,完成引用减一;任何引用计数为0的对象实例都可以被当做垃圾收集。
优点:执行效率高,只需要过滤出引用计数为0的即可并且程序执行受影响较小
缺点:无法检测出循环引用的情况,会导致内存泄露
比如下面的示例:
class MyObject{
private MyObject childNode;
}
class Reference{
MyObject myObject1 = new MyObject();
MyObject myObject2 = new MyObject();
myObject1.childNode = myObject2;
myObject2.childNode = myObject1;
}
上面的情况就是循环引用。
因为这个致命的缺点,现在主流的GC不采用这种垃圾收集算法进行垃圾回收。
可达性分析算法
通过判断对象的引用链是否可达决定对象是否可以被回收。
可达性分析算法是从图论中提出的,把所有的引用关系画一张图,以GC Root为起点向下搜索走过的路径称之为引用链。如果一个对象在这个图中没有任何引用链出现判定为不可达,同时判定这个对象不可达可以回收掉。
可以做为GC Root的对象:
- 虚拟机栈中引用的对象(栈帧中的本地变量表):new了一个实体赋值给局部变量,在局部变量被销毁之前,new出的对象会成为GC Root;
- 方法区中的常量引用的对象:在类里面定义一个常量,保存的是引用对象的地址,被保存的对象成了GC Root,别的对象引用到的时候就会形成GC Root关系;
- 方法区中的类静态属性引用的对象
- 本地方法栈中JNI(Native方法)的引用对象:被引用的非Java构建的对象
- 活跃线程的引用对象