给定一个仅在程序设置中使用的假设实用程序类:
class MyUtils {
private static MyObject myObject = new MyObject();
/*package*/static boolean doStuff(Params... params) {
// do stuff with myObject and params...
}
}
myObject 在不再使用时会被垃圾收集,还是会在程序的生命周期内一直存在?
给定一个仅在程序设置中使用的假设实用程序类:
class MyUtils {
private static MyObject myObject = new MyObject();
/*package*/static boolean doStuff(Params... params) {
// do stuff with myObject and params...
}
}
myObject 在不再使用时会被垃圾收集,还是会在程序的生命周期内一直存在?
加载类时不能选择静态变量进行垃圾回收。当相应的类加载器(负责加载此类)本身被收集为垃圾时,可以收集它们。
当且仅当垃圾收集器可以回收其定义的类加载器时,才可以卸载类或接口 [...] 引导加载器加载的类和接口可能不会被卸载。
静态变量由 ClassLoaders 引用的 Class 对象引用 - 所以除非 ClassLoader 以某种方式删除 Class(如果这甚至可能的话)或 ClassLoader 本身有资格收集(更有可能 - 考虑卸载 webapps)静态变量(或相反,它们引用的对象)不会被收集。
myObject 是一个引用,而不是一个对象。当一个对象没有引用指向它时,它会自动被垃圾回收,因为它是不可访问的。
因此,如果您取消引用静态引用“myObject”后面的对象,则它也可以被垃圾收集
myObject = null;
并且没有其他对该对象的引用。
但是,静态引用和变量会在程序的整个生命周期内保留。
如果您希望将临时对象用于静态初始化然后处理,您可以使用静态初始化块,例如
class MyUtils {
static
{
MyObject myObject = new MyObject();
doStuff(myObject, params);
}
static boolean doStuff(MyObject myObject, Params... params) {
// do stuff with myObject and params...
}
}
由于静态初始化块是一种特殊的静态方法,myObject 是一个局部变量,可以在块执行完成后进行垃圾回收。
我认为这回答了您的问题 - 除非该类来自特殊的类加载器并且卸载该类,否则基本上不会。
这里的关键是类实例的垃圾收集,即对象。ClassLoader 实例本质上是一个对象。因此,如果 Classloader 对象没有被垃圾回收,那么它们存储在堆中的任何引用(即静态的东西)几乎永远不会被垃圾回收。字符串池是个例外。
所以在你突然决定做之前
private static MyGiantClass myGiantObject = new MyGiantClass()
三思而后行,因为我已经学会了艰难的方式。