如何判断对象可被GC回收?

前言

        判断对象可被GC回收有两种办法分别是:引用计数算法根可达性算法

引用计数算法

        引用计数算法是一个已经被淘汰的算法,它是给每个对象加一个计数器,当有其他对象引用该对象时,该对象的计数器加一,当这个引用失效时,计数器就会减一,当该对象的计数器为零时,就会认为该对象可以被所回收。

        引用计数算法是一个简单并且高效的算法,但这种算法却有一个非常大的弊端。就是这种算法会造成对象的循环引用,导致即使这个对象不再被需要,仍然存在一个一直指向它的引用,使得计数器不为零,导致该对象无法被回收,造成内存空间的浪费。

        例如:假设存在对象A与对象B,他们之间的引用关系如图所示:

        即时A、B对象已经没有被其他对象所引用了,但他们之间仍然有一条引用指向对方,导致对象A、对象B的计数器都不为零,从而使得A、B对象都没法回收。

根可达性算法

        根可达性算法是JVM默认的算法,他的原理就是定义一系列的根,我们把这些根称为:GC Roots。从GC Roots开始向下搜索,中间查找的路径被称为:引用链

        当一个对象到GC Roots之间没有任何引用链相连接时,我们就认为这个对象可以被GC回收。

根可达性很好的解决了对象循环引用问题。

        例如:

        如上图所示,我们可以发现Object 6与Object 7、Object 8之间存在引用关系,但是他们到GC Roots之间没有任何一条引用链,因从Object 6、Object 7、Object 8都可被回收。

Java的四种引用类型

        在上述判断对象在何时能被GC回收是,我们多次提到了引用,那大家一定好奇什么是引用?引用有分为那些类型?一下我们就一一列举。

什么是引用?

举个例子:假设我们创建了一个创建了一个User对象,就像这样:new User(),但是也仅仅是创建了一个对象,并没有办法访问它。如果我们要访问这个对象,就必须指定一个User类型变量来表示这个对象:User user = new User(),user又被叫做"引用","="是指user这个引用指向User对象。 所以,java里对象的引用就是一个类类型的变量指向创建出来的对象

 引用有分为那些类型?

        在Java中引用被分为四种类型:强引用、软引用、弱引用、虚引用

强引用

        强引用是最频繁使用的一种引用,当一个对象具有强引用时,GC绝对不会回收这个对象。当内存空间不足,JVM宁愿抛出内存溢出错误,也不会随意回收强引用对象。

        如果强引用对象不再使用,可以通过弱化的方式回收该对象,弱化方式有两种分别是:

  1.  如果不在使用该对象,就及时将对象指向null,这时GC就会认为该对象不存在引用,但具体什么时候回收仍取决与GC算法
  2. 弱化的第二种方式,就是让不在使用的对象超出它的作用域范围,例如在方法中存在的对象当这个方法调用结束,GC就会回收这个对象

软引用

        软引用是对内存敏感的引用。如果内存空间充足,GC就不会回收软引用对象,如果内存空间不足,GC就会回收软引用对象。采用SoftReference来创建一个软引用对象

//强引用
String str = new String("hahaha");

//软引用
SoftReference<String> softReference = new SoftReference<String>(str);

 弱引用

        弱引用是不管内存是否充足,只要在GC扫描的过程中发现了弱引用对象,就会回收该对象。采用WeakReference创建弱引用对象

//强引用
String str = new String("hahaha");

//弱引用
WeakReference<String> weakReference = new WeakReference<>(str);

虚引用

        虚引用是最弱的一种引用关系,如果一个对象是虚引用,那么这个对象就和没有任何引用是一样的,随时都可能被回收。虚引用的主要作用是用来跟踪对象被垃圾回收的活动


版权声明:本文为w259149原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。