深入理解JAVA虚拟机—第三章垃圾收集器和内存分配策略(一)对象的引用和判断对象是否可用

 2019-12-22 10:51  阅读(710)
文章分类:JVM

对于java语言来说,在每次进行垃圾清理时,首先应该确认的,是这个对象是否还应该存活。对于不应该存活的则GC会对这些对象宣判死刑。这次我们探究一下JVM是如何判断对象是否应该存活的。

  • 引用计数法

引用计数法(Reference Couting),给每个对象添加一个引用计数器,当对象被引用后,计数器+1,当引用失效后,计数器-1。当某时刻计数器为0时,这个对象将无法再次使用。在很多领域引用计数法确实简单高效,但目前主流的JVM中都没有使用该方法,最主要的原因在于该方法很难解决对象之间的循环引用的问题。

  1. 从jdk1.2之后,java就更新了强引用,软引用,弱引用,虚引用等引用方法,如果只单独采用一个引用计数器则无法解决引用计数的问题。当然这点并不是根本的问题,根本的问题在于第二点。

  2. 当2个对象互相引用的时候,有得时候可能两个对象都无法访问了,但是因为2个对象互相引用着,最终导致这个对象的计数器则一直会大于1,对象在应该被回收的时候无法回收,造成内存浪费。因此,又有了第二种算法。

    • 可达性分析法

目前主流的JVM中都是使用可达性分析法(Reachability Analysis)判断对象是否存活。这个算法的基本思路就是通过很多GC根作为起始点,向下搜索,搜索的路径称之为引用链,当一个对象没有被任何引用链引用的时候,我们就可以认为该对象不可用。如下图:

2019120001367\_1.png

在JAVA中,可作为GCRoots的对象有以下几种:

虚拟机栈(栈帧中的本地变量表)中引用的对象

方法区静态属性引用的对象,常量引用的对象。

本地方法栈中(Native方法)引用的对象。

  • 介绍一下四种引用方法:

强引用:程序代码中直接存在的引用,类似Object o=new Object();只要这个强引用还在,那么GC永远不会收集该对象。

软引用:用来描述一些还有用,但是非必须的对象。对于这类对象,在系统即将发生内存溢出之前,将会对这些对象进行回收范围内进行第二次回收,如果这次回收之后还没有足够的内存。系统才会抛出内存溢出异常

弱引用:类似软引用,但是它的强度比软引用还会更弱一点,被弱化引用关联的对象只可以生存到下一次GC之前。GC工作时,无论内存是否可用,弱引用的对象都会被回收掉

虚引用:虚引用也称作幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。将对象设置成虚引用唯一的目的只是为了在该对象被回收的时候收到一个系统通知。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> 深入理解JAVA虚拟机—第三章垃圾收集器和内存分配策略(一)对象的引用和判断对象是否可用

相关推荐