首页 > 解决方案 > 对重新分配的静态对象引用进行 GC

问题描述

假设我有obj = new myobject(), whereobj被声明为另一个非静态类实例中的静态类字段。过了一会儿,我在同一个静态变量上创建了一个新的 myobject obj,从而“覆盖”了原来的赋值。

以下是我的问题:

  1. 分配的对象实例是否被 GC 可靠地释放,假设它不再可以从其他任何地方访问?
  2. 如果该字段被声明为非静态的,是否有任何区别?
  3. 在将静态 var 重新分配给新实例之前将其设置为 null 是否有区别?

标签: objectreferencestaticgarbage-collection

解决方案


... whereobj被声明为另一个非静态类实例中的静态类字段。

这可能意味着两件事之一;static字段或类的实例字段static

以下内容适用于这两种情况,除非另有说明。

1) 分配的对象实例是否被 GC 可靠地释放,假设它不再可以从其他任何地方访问?

这取决于您所说的“可靠”是什么意思。实际上并不能保证 GC 将运行(永远),或者它会在给定的运行中找到所有无法访问的对象,或者在程序的生命周期中将收集一个无法访问的对象。

但是您通常不需要保证这些东西。真正重要的是,您不会因为某些无法访问的对象而耗尽堆空间1

2)如果该字段被声明为非静态的,是否有任何区别?

这就是我一开始提到的问题发挥作用的地方:

  • 如果我们谈论的字段是static类的实例字段,那么它已经是非静态的。

  • 如果我们谈论的是static字段与实例字段,那么各个字段的生命周期就会有所不同。一个static字段在应用程序期间是可访问的(如果我们忽略动态创建的类加载器)。实例字段与它所属的对象一样长。

3)在将2静态变量重新分配给新实例null之前将其设置为有什么不同吗?

它没有任何区别。


1 - 我们需要在这里小心一点。JVM 可以触发“内存不足”事件,要么是因为内存不足,要么是因为 GC 花费了太多时间来收集垃圾。在后一种情况下,有可能(至少在理论上)在事件之前找不到给定的不可访问对象。也可以使用 Epsilon 收集器运行 JVM。这个收集器从不收集任何垃圾。

2 - 注意:您为变量赋值,而不是相反。您可以说为变量分配了一个值。但不是你写的。使用正确的词语有助于(你的)理解。


推荐阅读