Java垃圾收集之对象引用

引用计算方法

        Java中没有采用引用计数方法管理内存,最主要的原因是此方法很难解决对象间的循环引用问题。

 

        Java中采用的引用管理方法为:根搜索算法。基本思路是通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,所走过的路径称为“引用链(Reference Chain)”。当一个对象与其GC Roots之间没有任何通路的时候,就判定此对象可以被回收。

 

再谈引用

        Java1.2之前对引用的定义是:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,就称这块内存代表着一个引用。在1.2之后,Java将引用的概念进行了扩充,分为以下4种类型:

 

  • 强引用(Strong Reference)

        指一个引用直接指向一个对象,类似于 Object o = new Object(),只要强引用存在,GC就不可能将它回收。

 

  • 软引用(Soft Reference)

        用来描述一些还有用的,但并非必须的对象。对于软引用对象,系统在将要发生内存溢出异常之前,会将其列为回收对象并进行第二次回收。如果这次回收之后还是没有足够的内存,才会抛出内存溢出异常。Java中提供SoftReference类实现软引用。

 

  • 弱引用(Weak Reference)

        同样用来描述非必须对象,但强度比软引用更弱,被弱引用关联的对象只能生存到下一次垃圾回收发生之前。当GC工作时,不论内存是否充足,弱引用对象都会被列在回收范围内。 Java提供了WeakReference类实现弱引用。

 

  • 虚引用(Phantom Reference)

        也称为幽灵引用或者幻影引用,是最弱的一种引用类型。虚引用存在与否,都不会对一个对象的生存时间产生任何影响,也无法使用虚引用来获取对象实例。设置虚引用的唯一目的就是希望在此对象在垃圾回收的时候收到一个系统通知。Java提供了PhantomReference类实现虚引用。

 

对象的生存还是死亡

在根搜索算法中不可到达的对象,也不一定就是“非死不可”的对象,要真正的回收一个对象,至少要经历两次标记:如果在对对象进行根搜索之后没有发现有与对应的GC Roots相连的引用链,那么它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。

当对象被判定为“有必要执行finalize()方法”,那么这个对象会被放置在一个名为“F-Queue”的队列之中,并在稍后又一条由虚拟机自动建立、低优先级的Finalizer线程去执行每个对象的finalize()方法,但不保证一定会等待每个对象的finalize方法执行结束,因为如果有对象的finalize方法很耗时或者干脆就是死循环,那么整个F-Queue中的对象都会处于等待状态甚至虚拟机崩溃。

finalize()方法是对象逃脱被回收的最后一次机会,GC会对F-Queue中的对象进行第二次小规模标记,如果对象想要逃脱被回收的命运,只要在finalize()方法中与引用链上的任何一个对象建立关联即可。

注意,任何对象的finalize()方法只会被执行一次。

 

不建议复写finalize()方法来进行类似资源回收的行为,使用try-finally或者其他方式都可以做的更好更及时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值