【问题标题】:Are static fields open for garbage collection?静态字段是否为垃圾收集打开?
【发布时间】:2010-10-01 23:13:45
【问题描述】:

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

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

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

【问题讨论】:

    标签: java static garbage-collection static-members


    【解决方案1】:

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

    查看JLS Section 12.7 Unloading of Classes and Interfaces

    可以卸载一个类或接口 当且仅当它的定义类 loader 可能会被垃圾回收 收集器 [...] 类和接口 由引导加载程序加载的可能不会 被卸载。

    【讨论】:

    • @bruno,根据您的链接,这是否意味着类加载器持有对其加载的每个类的引用,即使加载的类没有静态成员?
    • @brunoconde,我认为这实际上不是真的。究竟哪一段是这么说的? (请在stackoverflow.com/questions/405364/…继续讨论)
    • 类加载器何时有资格进行垃圾回收。 ?
    • @RohitBandil - 当它无法访问时。
    【解决方案2】:

    静态变量由 ClassLoader 引用的 Class 对象引用 - 所以除非 ClassLoader 以某种方式丢弃 Class(如果这甚至可能的话)或者 ClassLoader 本身符合收集条件(更有可能 - 考虑卸载 webapps)静态变量(或者更确切地说,它们引用的对象)不会被收集。

    【讨论】:

    • Class 不包含静态变量的对象是否会被其类加载器引用?
    【解决方案3】:

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

    所以如果你取消引用静态引用“myObject”后面的对象

    myObject = null;
    

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

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

    【讨论】:

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

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

    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()...
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

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

      所以在你突然决定做之前 private static MyGiantClass myGiantObject = new MyGiantClass() 三思而后行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-29
        • 2011-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 2011-01-26
        相关资源
        最近更新 更多