弱引用和强引用GC行为



我声明了一个strong reference -

Data data = new Data();

为了使它符合垃圾收集的条件,我将instance设为null-

data = null;

现在,当我将引用设为null时,对象是不可访问的,并且在GC运行时被垃圾收集。

使用WeakReference -

Data data = new Data();
WeakReference<Data> weakRef = new WeakReference<Data>(data);

当我将引用变量设置为null时,它将有资格进行垃圾收集。

data = null;

当我们使用StrongReference时,我们将它的引用设为null以获取GC。在weakreference的情况下我们需要引用对象null来使它成为GC。两者的区别是什么?在强引用的情况下,如果我们只是引用对象null,它将符合GC的条件,并将在GC运行时收集。

如果你有纠缠的对象(即对象是不可访问的),垃圾收集器被允许收集它们并清除它们。注意措辞:是允许的。这意味着垃圾收集器可以决定不收集它们。实际上,根本不能保证对象会被垃圾收集。

由SoftReference或WeakReference管理的对象与删除的强引用管理的对象之间的区别在于垃圾收集策略:

  • 软可及对象将被收集,如果需要内存。
  • 弱可及对象将在第一次尝试收集。
  • 否则不可达的对象将在收集器的策略中收集(这可能类似于软可达,并且也可以在启动时使用一些JVM参数进行调整)。

尽管如此,这些都是关于最可能的策略的假设,但是垃圾收集器可能会以另一种方式决定。

注意:在局部作用域中使用弱引用和软引用是没有意义的。它们最可能在实例字段中使用,并且必须始终注意所引用的对象可能已经被收集的事实。

不同之处在于,您可以通过调用weakRef.get()并测试它是否返回null来知道GC是否收集了数据。

虽然这篇文章已经有了一些很好的答案,但我还想补充一点。在这个问题中,

"当我们使用StrongReference时,我们使它的引用为空以获得GC。在weakreference的情况下,我们还需要对对象null进行引用以使其GC。两者的区别是什么?

假设我们有一个对象,它被两个强引用xy引用。如果我们将x = null设置为被x引用的对象,那么它还没有资格被垃圾收集,因为我们仍然让y引用相同的对象。读取y仍然会输出非空对象。

现在假设我们有一个对象,它有一个强引用,比如x和一个弱引用,y。现在,如果我们设置x = null,我们可以确保该对象将符合垃圾收集的条件。WeakReference不会阻止这个对象被垃圾收集。

在弱引用上调用get()方法可能会在对象被垃圾收集后立即返回null。因此,建议在使用之前总是检查返回的对象。

(重要)我们还需要确保在任何长期存在的硬引用(如instance fields)中不保留返回的非空值。如果我们得到一个弱引用,那么如果我们需要的话,我们应该使用弱引用作为实例字段,并且在任何方法中获取对象,都可以使用局部变量来保存返回的对象,应该检查它是否为空,如果为空,则可以使用该对象进行进一步处理。

对于softrereferences来说,这是一个额外的问题,它们防止对象被垃圾收集,直到内存不足(低于阈值)。

最新更新