GC ROOTS及强弱引用的区别

众所周知JVM在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行垃圾回收之前,第一件事就是要判断有哪些对象已经死去(即不可能在被任何途径使用的对象)

引用计数算法

在一个对象中添加引用计数器,每有一个地方引用它时就把这个计数器加一;当引用失效时,计数器值就减一;任何时刻只要计数器为零的对象就是不可能在被使用的。
引用计数法虽然占用了一些额外的内存空间进行技术,但是它的原理很简单,实现和判定效率也很高。这是它的优势所在,但是在Java里面主流的JVM都没有选择引用计数法来进行内存管理。因为这个算法有很多例外的情况没有考虑到,使用的话必须要配合大量的额外处理才可以正确的工作,例如很难解决对象之间的循环引用问题。

可达性分析算法

当前主流的内存管理系统基本上都是使用可达性分析算法来判断对象是否是存活的。这个算法的基本思路就是通过一系列称为"GC roots"的根对象来作为起始节点集,从这些节点来时根据引用关系向下搜索,过程中所走过的路径称为"引用链",如果这个对象到GC Roots间没有任何引用链相连,或者是用图论的话来说就是从GC Roots到这个对象不可达时,则证明这个对象是不可能再被使用的。
如下图所示:

在这里插入图片描述

在Java的技术体系中固定可作为GC Roots对象的包括以下几种:

  1. 在虚拟机栈中引用道德对象,即栈帧中的本地变量表,如参数,局部变量,临时变量等
  2. 在方法区中类静态属性引用的对象,如类中引用类型的静态变量
  3. 在方法区中常量引用的对象,如字符串常量池中的引用
  4. Native方法引用的对象
  5. JDK中内部的引用,如基本数据类型的类对象,异常类对象,类加载器等等
  6. 所有被同步锁持有的对象

除了这些固定的GC Roots集合以外,根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还会有其他对象临时的加入GC Roots中。

JDK中的引用

  1. 强引用是最传统的引用的定义,是指在程序代码中普遍存在的引用赋值,即类似"Object obj = new Object()"这种引用关系就是强引用。无论在任何情况下,只要强引用关系存在,垃圾回收器就永远不会回收这部分对象。
  2. 软引用是用来描述一些还有用,但不是必须的对象。只要被软引用关联的对象,在系统将要开始内存溢出之前,会把这些对象列进回收范围之中进行二次回收,如果这次回收还没有足够的内存时就会抛出内存溢出的异常。JDK提供SoftReference来实现软引用。
  3. 弱引用是用来描述那些非必须对象,但是它的强度会比软引用弱一些,被弱引用关联的对象只能生存到下一次的垃圾回收发生为止。当垃圾收集器开始工作,无论当前内存是否够用都会回收掉只被弱引用关联的对象。JDK提供WeakReference来实现弱引用。
  4. 虚引用称为"幽灵引用"或者"幻引用",它是最弱的一种引用关联。一个对象是否有虚引用的存在,完全不会影响它的生存时间,也无法通过一个虚引用来获取对象实例。当一个对象设置虚引用关联的目的就是为了在这个对象被回收时收到一个系统的通知。JDK提供了PhantomReference来实现。

对象死亡前夕

如果对象在进行可达性分析算法分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。假如对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,那么虚拟机将这两种情况视为"没有必要执行"。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值