JVM:GC-判断对象是否可以回收?

今天开始GC,也就是垃圾回收。
GC主要做三个事情:
1、什么对象可以回收
2、什么时候进行回收
3、如何回收
jvm里的垃圾就是对象,指无用的对象,在真正执行垃圾回收前,必须要判断对象是否是无用,是否可以回收,那么jvm是如何来判断一个对象能否回收呢?
今天就来探讨一下。

引用计数算法

方式:给对象维护一个引用计数器,当有一个地方引用到它,则计数器加1,当有引用失效,则计数器减1,当为0时,说明没有地方引用到这个对象。
优点:实现简单、效率高
缺点:无法解决循环引用。
例:

class Instance{
public Object obj;
public static void main(String[] args){
Instance a = new Instance();
Instance b = new Instance();
a.obj=b;
b.obj=a;
a=null;
b=null;
//a/b由于持有对方的引用,无法被回收,事实上他们已经用不到可以被回收
}
}

可达性分析算法

方式:从一系列被称为GC ROOT的对象开始,向下搜索,搜索走过的路径称为引用链,当一个对象到GC ROOT之间没有引用链,说明这个对象不可用。

可作为GC ROOT的对象:
虚拟机栈中引用的对象,
方法区内类的静态属性引用的对象,
方法区常量引用的对象,
本地方法栈中引用的对象

finalize

当一个对象被判定为不可达对象后,也并不是非死不可。
在通过可达性分析算法判断没有引用链使之与GC ROOT相连,会判断该对象是否有必要执行finalize方法:
假如重写了finalize,并且未调用过,则说明有必要执行。

判断有必要执行finalize的对象,会被放入一个队列,有jvm建立的低优先级的Finalizer线程去执行。

当在finalize中自救成功的对象,就会在第二次标记时移除即将回收的集合。
自救失败的就会被回收,不会在执行finalize。

所谓自救就是把自己与引用链上的一个对象关联起来。

JDK1.2,引用概念扩充

强引用:在可达性分析中判断为对象不可达,则自救失败的对象会被回收
软引用:在内存不足时会被回收
弱引用:发生GC就会被回收
虚引用:与普通引用没区别,不影响GC的回收,只是在回收的时候,虚引用引用到的对象会进行一个引用对象,开发人员可以在回收前做一些操作。

方法区内能否GC

方法区内也可以进行GC,只是相对于堆内存来说回收的性价比不高。
方法区内的回收主要就是 废弃常量和无用的类。
废弃常量的回收条件桶堆内对象,只要没有地方引用到它即可参与回收。
判断无用的类需要下面三个条件:
1、该类对象的实例都被回收
2、该类的类加载器被回收
3、该类的Class对象不存在引用,无法在任何地方通过反射访问

猜你喜欢

转载自blog.csdn.net/qq_28605513/article/details/85094223