2014-10-17 95 views
0

我的应用程序在两种环境中工作正常,但在验收测试环境中存在内存泄漏。 JVM堆转储显示堆满98%java.object.finalize()(如果我没有记错的话,GC日志声明GC正在越来越频繁地执行Full GC,直到JVM发出内存不足 - 错误。java堆满Java finalize()调用

这可能是什么原因造成的?应用程序在所有环境中都是一样的,但操作系统和网络在问题环境中略有不同,Java在所有环境中都是一样的。 Object Finalize(),但由于某种原因它没有完成?我正在使用JBoss EAP 5.

+0

尝试使用jProfiler,它是一个非常棒的工具来查找泄漏,您将能够找到导致此问题的类。 – 2014-10-17 13:28:38

+2

你是否为任何对象重写了'finalize()'? – 2014-10-17 13:28:41

+0

我们还没有重写finalize()在任何地方 – user1340582 2014-10-21 05:30:35

回答

1

有可能创建垃圾,要求终止速度比它能够最终化的速度快当一个对象被确定为无法访问时,符合收集条件)并且要求完成,它将被添加到终结器队列中而不是立即收集。在完成终结器后的下一个GC中,可以收集对象。换句话说,最终化会延迟内存的恢复。

有一个执行所有finalize方法的线程,默认情况下它的运行优先级与所有其他线程相同。如果你有很多创建垃圾的线程需要完成,他们可以比一个终结器线程能够执行finalize()方法更快地产生垃圾。另外,如果你最终确定的方法不是很快,你只会让这个问题变得更糟。

总之,您可能有太多和/或太慢的方法来执行。这可能是因为在一个问题环境中,敲定方法较慢?或者你有更多的处理能力,所以你更快地创建垃圾?

我已经遇到过这个问题。为了缓解它,我提高了终结器线程的优先级。这样做的诀窍是在初始化过程中创建一段垃圾,它会覆盖finalize()并在最终确定期间更改当前线程中的线程优先级。在这种情况下更改终结器线程的优先级足以解决问题,但不能保证执行该技巧。

+0

嗯听起来像一个黑客? :)问题环境比没有问题的环境更强大。我们也不会重写finalize。 – user1340582 2014-10-21 06:31:38

+0

我的解决方法绝对是一种破解。根本原因是JVM中的设计错误。这个bug往往只会在更强大的环境中体现出来,因为JVM最终确定的能力并没有随着核心的添加而扩展,但是应用程序创建垃圾的能力往往随着核心的添加而线性扩展。 – Rob 2014-10-21 15:59:56