给定一个仅在程序设置中使用的假设实用程序类:
class MyUtils {
private static MyObject myObject = new MyObject();
/*package*/static boolean doStuff(Params... params) {
// do stuff with myObject and params...
}
}
myObject 在不再使用时会被垃圾收集,还是会在程序的生命周期内一直存在?
加载类时不能选择静态变量进行垃圾回收。当相应的类加载器(负责加载此类)本身被收集为垃圾时,可以收集它们。
查看JLS Section 12.7 Unloading of Classes and Interfaces
当且仅当垃圾收集器可以回收其定义的类加载器时,才可以卸载类或接口 [...] 引导加载器加载的类和接口可能不会被卸载。
静态变量由 ClassLoaders 引用的 Class 对象引用 - 所以除非 ClassLoader 以某种方式删除 Class(如果这甚至可能的话)或 ClassLoader 本身有资格收集(更有可能 - 考虑卸载 webapps)静态变量(或相反,它们引用的对象)不会被收集。
Class
对象是否会被其类加载器引用?
myObject 是引用而不是对象。当一个对象没有引用指向它时,它会自动被垃圾回收,因为它是不可访问的。
因此,如果您取消引用静态引用“myObject”后面的对象,则它也可以被垃圾收集
myObject = null;
并且没有其他对该对象的引用。
但是,静态引用和变量会在程序的整个生命周期内保留。
static block
末尾将对象设置为 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()
之前,请三思而后行,因为我已经学会了艰难的方法。
不定期副业成功案例分享