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


95

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

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

不再使用myObject时会对其进行垃圾回收,还是在程序的生命周期内一直存在?

Answers:


112

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

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

仅当垃圾回收器可以回收定义的类加载器时,才可以卸载类或接口。引导加载器加载的类和接口可以不卸载。


@bruno,通过您的链接,这是否意味着类加载器持有对其加载的每个类的引用,即使加载的类没有静态成员也是如此?
Pacerier,2014年

@brunoconde,我不认为这是真的。究竟哪段说明了这一点?(请继续在stackoverflow.com/questions/405364/…上进行讨论)
Pacerier,2014年

当类加载器有资格进行垃圾回收时。?
罗希特·班迪尔

@RohitBandil-无法访问时。
斯蒂芬·C

55

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


1
Class包含静态变量的对象会被其类加载器引用吗?
Pacerier,2014年

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是局部变量,可以在该块完成执行后进行垃圾回收。


13

myObject是引用,而不是对象。如果没有引用指向对象,则该对象将自动被垃圾回收,因为该对象不可访问。

因此,如果使用取消引用静态引用“ myObject”后面的对象,则也可以对其进行垃圾回收。

myObject = null;

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

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


欢迎来到StackOverflow!将对象设置null为的结尾static block是一个可行的选择。但就我而言,该对象的生存期需要比静态块更长。对象的最终用途不是很具体。因此,我问有关利用垃圾收集器的问题。
Michael Deardeuff 2014年

7

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


0

这里的关键是类实例(即对象)的垃圾回收。本质上,ClassLoader实例是一个Object。因此,如果未对Classloader对象进行垃圾回收,则几乎永远不会垃圾回收存储在堆中的所有对它们的引用(即静态内容)。字符串池是一个例外。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.