ChatGPT解决这个技术问题 Extra ChatGPT

静态字段是否为垃圾收集打开?

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

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

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


S
Sergey Maksimenko

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

查看JLS Section 12.7 Unloading of Classes and Interfaces

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


@bruno,根据您的链接,这是否意味着类加载器持有对其加载的每个类的引用,即使加载的类没有静态成员?
@brunoconde,我认为这实际上不是真的。究竟哪一段是这么说的? (请继续在 stackoverflow.com/questions/405364/… 上讨论)
当类加载器有资格进行垃圾收集时。 ?
@RohitBandil - 当它无法访问时。
@StephenC 如果它是一个只包含静态字段/方法的类,即一个从未实例化的类怎么办?
J
Jon Skeet

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


不包含静态变量的 Class 对象是否会被其类加载器引用?
F
Felix Keil

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

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

myObject = null;

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

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


欢迎来到 StackOverflow!在 static block 末尾将对象设置为 null 是一个可行的选择。但是,在我的情况下,对象的生命周期需要比静态块长。该对象的最终用途不是很具体;因此,我询问有关使用垃圾收集器的问题。
f
finnw

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

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

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

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


或者你可以做“MyObject myObject = new MyObject();”直接在 doStoff()...
C
Community

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


h
ha9u63ar

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

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