静态字段是否打开以进行垃圾回收?

时间:2009-01-17 09:02:50

标签: java static garbage-collection static-members

给出一个仅在程序设置中使用的假设实用程序类:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

当myObject不再被使用时会被垃圾收集,还是会在程序的生命周期中保留?

6 个答案:

答案 0 :(得分:105)

加载类时,无法为垃圾回收选择静态变量。当相应的类加载器(负责加载此类)本身被收集用于垃圾时,可以收集它们。

查看JLS Section 12.7 Unloading of Classes and Interfaces

  

可以卸载类或接口   当且仅当它的定义类   装载机可能被垃圾回收   collector [...]类和接口   由引导加载程序加载可能不会   被卸下。

答案 1 :(得分:47)

静态变量由ClassLoaders引用的Class对象引用 - 除非ClassLoader以某种方式丢弃Class(如果可能的话)或者ClassLoader本身有资格进行收集(更可能是 - 考虑卸载webapps)静态变量(或者更确切地说,它们引用的对象)将不会被收集。

答案 2 :(得分:13)

如果您希望临时对象用于静态初始化然后处理,您可以使用静态初始化块,例如

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

由于静态初始化块是一种特殊的静态方法,myObject是一个局部变量,在块完成执行后可以进行垃圾收集。

答案 3 :(得分:9)

myObject是引用,而不是对象。 当没有引用指向它时,对象会自动进行垃圾回收,因为它无法访问。

如果你用

取消引用它,那么静态引用“myObject”背后的对象也可以被垃圾收集。
myObject = null;

并且没有其他对此对象的引用。

然而,静态引用和变量在程序的生命周期内仍然存在。

答案 4 :(得分:6)

我认为this回答了你的问题 - 除非该类来自特殊的类加载器并且卸载了类,否则基本上不会。

答案 5 :(得分:0)

这里的关键是类实例的垃圾收集,即对象。 ClassLoader实例本质上是一个Object。因此,如果Classloader对象不是垃圾收集的,那么存储在堆中的它们的任何引用(即静态内容)几乎都不会被垃圾收集。字符串池是个例外。

所以在你突然决定做之前 private static MyGiantClass myGiantObject = new MyGiantClass() 当我学会了艰难的道路时,请三思而后行。