垃圾收集器是否会删除静态最终对象?

时间:2013-09-02 08:18:47

标签: java garbage-collection

我之前在Java中的服务中使用自定义对象始终在后端运行,我有时会收到Bug报告,其中跟踪显示NULL_POINTER_EXCEPTION,因为垃圾收集器破坏了对象。由于我拥有所有高端设备,我无法测试这是否会导致静态最终对象被垃圾收集器破坏?

3 个答案:

答案 0 :(得分:6)

在普通的Java应用程序中(我不确定Android),只有当卸载了正确的ClassLoader时,静态最终引用的对象才会被GC。

例如,当在容器(例如Tomcat)中拥有多个Web应用程序时,取消部署每个Web应用程序,取消应用程序的ClassLoader,因此应用程序的静态最终引用的对象将被GCed。但是其他ClassLoader加载的对象(例如其他web-app的ClassLoader,常见的ClassLoader,boot-strap ClassLoader)将不会被GC。

所以问题的答案是:它取决于ClassLoader是否被取消激活。

答案 1 :(得分:3)

  

垃圾收集器是否会删除静态最终对象?

我可以想到三种可能发生这种情况的情况:

  1. 使用static加载类的类加载器变得无法访问。但是这只能在 之后发生你的代码达到了一个没有任何东西可能会注意到该对象是GC的点!

  2. 有些东西使用“讨厌的反思技巧”将null分配给static final。 (是的,可以做到......)

  3. 有些东西巧妙地破坏了堆;例如一些有害的JNI / JNA代码。

  4. 请注意,由于您(显然)观察 GC'd对象的效果,因此 CAN NOT 是类加载器GC的直接结果。必须发生其他事情才能使类加载器和final static成为GC'...如果这就是实际发生的事情。


    实际上,我怀疑您的问题与GC无关。相反,我怀疑由于未记录的未经检查的异常,您的服务正在死亡。

    以外的线程上未捕获的异常的默认行为是静默忽略它们。

    我建议您检查服务线程是否记录了所有异常,可以使用catch方法中的run()或“未捕获的异常处理程序”。

答案 2 :(得分:1)

JVM使用标记扫描GC算法,该算法必须检查GC“根”位置中的所有实时引用(如当前调用堆栈中的所有对象)。每个活动对象被“标记”为活着,活动对象引用的任何对象也被标记为活着。

完成标记阶段后,GC扫描堆,释放所有未标记对象的内存(并为剩余的活动对象压缩内存)。

我要说“不,'最后'的modifer无法帮助GC减少工作量。”