Java 静态字段是否对垃圾收集开放?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/453023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:48:46  来源:igfitidea点击:

Are static fields open for garbage collection?

javastaticgarbage-collectionstatic-members

提问by Michael Deardeuff

Given an hypothetical utility class that is used only in program setup:

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

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

will myObject be garbage collected when it is no longer being used, or will it stick around for the life of the program?

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

采纳答案by bruno conde

Static variables cannot be elected for garbage collection while the class is loaded. They can be collected when the respective class loader (that was responsible for loading this class) is itself collected for garbage.

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

Check out the JLS Section 12.7 Unloading of Classes and Interfaces

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

A class or interface may be unloaded if and only if its defining class loader may be reclaimed by the garbage collector [...] Classes and interfaces loaded by the bootstrap loader may not be unloaded.

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

回答by Tom

I think thisanswers your question - basically not unless the class comes from a special class loader and that unloads the class.

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

回答by Jon Skeet

Static variables are referenced by Class objects which are referenced by ClassLoaders -so unless either the ClassLoader drops the Class somehow (if that's even possible) or the ClassLoader itself becomes eligible for collection (more likely - think of unloading webapps) the static variables (or rather, the objects they reference) won't be collected.

静态变量由类加载器引用的类对象引用 - 所以除非类加载器以某种方式删除类(如果这甚至可能)或者类加载器本身有资格收集(更有可能 - 想想卸载 webapps)静态变量(或相反,他们引用的对象)不会被收集。

回答by finnw

If you want a temporary object to be used for static initialisation then disposed of, you can use a static initialiser block, e.g.

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

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

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

since the static initialiser block is a special kind of static method, myObject is a local variable and can be garbage collected after the block finishes executing.

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

回答by Felix Keil

myObject is a referenceand not an object. An object is automatically garbage collected when no reference points to it because it is unreachable.

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

So also the object behind a static reference "myObject" can be garbage collected if you dereference it with

因此,如果您取消引用静态引用“myObject”背后的对象

myObject = null;

and there are no other references to this object.

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

However static references and variables remain for the lifetime of your program.

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

回答by ha9u63ar

The key here is the Garbage Collection of Class instances i.e. Objects. ClassLoader instance is, in essence, an Object. So if the Classloader object is not garbage collected, any references of them stored in heap (i.e. static stuff) will almost never be garbage collected. The exception is String pool.

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

So before you suddenly decide to do private static MyGiantClass myGiantObject = new MyGiantClass()Think twice as I have learnt the hard way.

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