深入理解Java虚拟机之引用与对象回收

深入理解Java虚拟机之引用与对象回收

      在JDK1.2之前Java对引用的定义是这样的:如果栈中reference数据指向的是另一块内存的其实地址,就称之为这个内存的一个引用。这种定义比较纯粹但是过于狭隘,因为这种情况下一个对象只有两种状态,被引用和未被引用,但是如果有一些我们希望当内存够用的时候保留下来,当内存不够用的时候再回收掉的对象,我们就无法简单的用被引用和未被引用这两种状态来表述了。
      基于这种需求,在JDK1.2之后对引用的概念进行了扩展,将引用细分为四类:

  • 1、强引用,就是我们普通情况下进行new的对象,就是强引用。强引用的对象即使内存不够用了,也不会对强引用的对象进行回收,而是会报出OutOfMemoryException的错误。
  • 2、软引用,用来表述那些还用得到但是不是必需的对象。只有当内存即将不够用的时候,虚拟机才会将软引用的对象进行回收,如果回收完软引用的对象内存还是不够用那么就会报出OutOfMemoryException的错误。要实现软引用需要借助SoftReference类来实现。
  • 3、弱引用,同软引用一样也是用来描述那些非必需的对象的,但是他的强度较软引用更弱一些,在下次GC动作发生的时候不论内存是否够用都会对弱引用对象进行回收,弱引用需要借助WeakReference类来实现,Java集合类中的WeakHashMap就是采用的弱引用。
  • 4、虚引用,也成为幻影引用和幽灵引用,它是最弱的一种引用方式。一个对象是否具有虚引用不会影响这个对象的存活时间,也无法通过虚引用获取一个对象实例,它的唯一作用就是在这个对象被回收的时候收到一个系统通知。实现虚引用需要借助PhantomReference类来实现。

      即使是在可达性分析算法中不可达的对象也并不意味着一定会被回收,要回收一个对象,至少要经过两次标记的过程,如果一个对象在可达性分析中没有和“GC Roots”有引用链的存在,就会被第一次标记并进行一次筛选,筛选的条件是没有必要执行这个对象的finalize()方法,当对象没有覆盖finalize()方法或者对象的finalize()方法已经被执行过一次了,那么就会被视为没有必要执行。
      如果对象被判定为有必要执行finalize()方法,那么就会将这个对象放到一个F-Queue的队列当中,然后在虚拟机建立的低优先级的Finalizer线程中执行,当然虚拟机不一定会等这个对象的finalize()方法执行完毕之后才会对这个对象进行回收,因为如果这个对象的finalize()方法中有一个死循环或者执行很缓慢那么虚拟机一样会将这个对象回收掉。而finalize()方法是对象对自己进行“拯救”的唯一也是最后一次机会,只要将自己重新赋给一个变量就可以,在GC对F-Queue中的对象进行第二次标记的时候会将“拯救”了自己的对象移出
即将被回收的集合,如果这个时候对象没有“拯救”自己,那么它就真的被回收了。
      这里要注意的是,同一个对象finalize()方法只会被执行一次,下一次GC会直接判断这个对象的finalize()已经被执行过一次了,也就会判断对象为没有必要执行finalize()方法。也就是说,对象的“自我拯救”只有一次机会。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值