7

我以前在 Java 服务中使用过自定义对象,该服务始终在后端运行,有时我会收到带有跟踪的错误报告,这些跟踪显示NULL_POINTER_EXCEPTION对象被垃圾收集器销毁。由于我拥有所有高端设备,因此无法测试静态最终对象是否被垃圾收集器销毁?

4

3 回答 3

6

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

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

所以你的问题的答案是:这取决于 ClassLoader 是否被停用。

于 2013-09-02T08:59:05.653 回答
3

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

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

  1. 使用 加载类的类加载器static变得无法访问。但这只会发生您的代码达到没有任何东西可能注意到该对象已被 GC 处理的程度之后!

  2. 某些东西使用了“讨厌的反射技巧”来分配nullstatic final. (是的,可以做到……)

  3. 有些东西正在巧妙地破坏堆;例如一些错误的 JNI / JNA 代码。

请注意,由于您(显然)正在观察对象被 GC 的影响,因此它不能是类加载器被 GC 的直接结果。必须发生其他事情才能使类加载器和final staticGC'ed 成为可能……如果这就是这里实际发生的情况。


实际上,我怀疑您的问题与 GC 无关。相反,我怀疑您的服务由于未记录的未经检查的异常而死亡。除“main”之外的线程上未捕获的异常的默认行为是默默地忽略它们。

我建议您检查您的服务线程是否正在记录所有异常,无论是catchrun()方法中还是在“未捕获的异常处理程序”中。

于 2013-09-02T09:29:50.640 回答
1

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

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

我会说“不,'final' 修饰符不会帮助 GC 减少其工作量”。

于 2013-09-02T08:22:38.793 回答