给出一个仅在程序设置中使用的假设实用程序类:
class MyUtils {
private static MyObject myObject = new MyObject();
/*package*/static boolean doStuff(Params... params) {
// do stuff with myObject and params...
}
}
当myObject不再被使用时会被垃圾收集,还是会在程序的生命周期中保留?
答案 0 :(得分:105)
加载类时,无法为垃圾回收选择静态变量。当相应的类加载器(负责加载此类)本身被收集用于垃圾时,可以收集它们。
查看JLS Section 12.7 Unloading of Classes and Interfaces
可以卸载类或接口 当且仅当它的定义类 装载机可能被垃圾回收 collector [...]类和接口 由引导加载程序加载可能不会 被卸下。
答案 1 :(得分:47)
静态变量由ClassLoaders引用的Class对象引用 - 除非ClassLoader以某种方式丢弃Class(如果可能的话)或者ClassLoader本身有资格进行收集(更可能是 - 考虑卸载webapps)静态变量(或者更确切地说,它们引用的对象)将不会被收集。
答案 2 :(得分:13)
如果您希望临时对象用于静态初始化然后处理,您可以使用静态初始化块,例如
class MyUtils {
static
{
MyObject myObject = new MyObject();
doStuff(myObject, params);
}
static boolean doStuff(MyObject myObject, Params... params) {
// do stuff with myObject and params...
}
}
由于静态初始化块是一种特殊的静态方法,myObject是一个局部变量,在块完成执行后可以进行垃圾收集。
答案 3 :(得分:9)
myObject是引用,而不是对象。 当没有引用指向它时,对象会自动进行垃圾回收,因为它无法访问。
如果你用
取消引用它,那么静态引用“myObject”背后的对象也可以被垃圾收集。myObject = null;
并且没有其他对此对象的引用。
然而,静态引用和变量在程序的生命周期内仍然存在。
答案 4 :(得分:6)
我认为this回答了你的问题 - 除非该类来自特殊的类加载器并且卸载了类,否则基本上不会。
答案 5 :(得分:0)
这里的关键是类实例的垃圾收集,即对象。 ClassLoader实例本质上是一个Object。因此,如果Classloader对象不是垃圾收集的,那么存储在堆中的它们的任何引用(即静态内容)几乎都不会被垃圾收集。字符串池是个例外。
所以在你突然决定做之前
private static MyGiantClass myGiantObject = new MyGiantClass()
当我学会了艰难的道路时,请三思而后行。