我已经编写了一个基类,用于向存储库发出请求。它有一个静态字段,用于应用程序中的某些目的。
public abstract class RepositoryRequest {
private static String version;
{
version = 2.0; //Actual read is happening from some configuration file.
}
protected String getVersion() {
return version;
}
}
我们有多个请求POJO,它们扩展了这个抽象类
public class ARepositoryRequest extends RepositoryRequest {
//Some properties here
@Override
public String toString() {
return "Some string generated by some logic" + getVersion();
}
}
类似地,其他类也在扩展和重写toString()方法。
我对这些POJO对象的垃圾收集有一些疑问:
1. Would this kind of usage of static variable will not let the POJO objects garbage collected?
2. Is there any issue with Objects/Classes in their garbage collection?
不,静态字段不会阻止子类的垃圾收集(如果阻止了,这将是一个主要问题,使静态字段在垃圾收集语言中几乎不可用!)
您可以通过向类中添加终结器来测试这一点,然后在循环中创建一堆终结器,调用System.gc()
来引发垃圾收集。如果您的finalize()
方法打印出一条消息,您可以看到GC正在发生。
protected void finalize() throws Throwable {
System.out.println("Finalize!");
}
原因是静态字段属于类对象(RepositoryRequest
)。当该类的任何实例存在时,都不能对其进行垃圾收集,并且通常无论如何都不会卸载类,除非它们的ClassLoader是垃圾收集的,这是不寻常的。
但是,分配给实例的所有内存都可以安全地回收,而不会对类对象产生任何影响。
在的情况下,静态成员可以阻止其他数据的GC;例如,如果将普通Collection中类的所有实例缓存为静态字段,则它们不可能是GCd(因为仍然有对它们的"活动"引用)。
此处已回答问题:静态字段是否为垃圾收集打开?
正在复制答案:"在加载类时,不能选择静态变量进行垃圾收集。当相应的类加载程序(负责加载该类)本身进行垃圾收集时,可以收集静态变量。
查看JLS第12.7节卸载类和接口
类或接口可以被卸载,当且仅当其定义类加载器可以由垃圾收集器回收[…]类和由引导加载程序加载的接口可以不被卸载。">