98

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

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

myObject 在不再使用时会被垃圾收集,还是会在程序的生命周期内一直存在?

4

6 回答 6

123

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

查看JLS 第 12.7 节卸载类和接口

当且仅当垃圾收集器可以回收其定义的类加载器时,才可以卸载类或接口 [...] 引导加载器加载的类和接口可能不会被卸载。

于 2009-01-17T09:44:14.597 回答
61

静态变量由 ClassLoaders 引用的 Class 对象引用 - 所以除非 ClassLoader 以某种方式删除 Class(如果这甚至可能的话)或 ClassLoader 本身有资格收集(更有可能 - 考虑卸载 webapps)静态变量(或相反,它们引用的对象)不会被收集。

于 2009-01-17T09:33:21.763 回答
15

myObject 是一个引用,而不是一个对象。当一个对象没有引用指向它时,它会自动被垃圾回收,因为它是不可访问的。

因此,如果您取消引用静态引用“myObject”后面的对象,则它也可以被垃圾收集

myObject = null;

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

但是,静态引用和变量会在程序的整个生命周期内保留。

于 2014-07-11T12:49:09.493 回答
14

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

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

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

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

于 2009-01-17T18:49:44.370 回答
7

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

于 2009-01-17T09:12:24.503 回答
0

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

所以在你突然决定做之前 private static MyGiantClass myGiantObject = new MyGiantClass() 三思而后行,因为我已经学会了艰难的方式。

于 2018-05-02T22:31:53.033 回答