为什么我的Tomcat应用程序的内存使用量不断增加?

11

我的应用在运行在 Windows Server 2000 上。内存使用量不断增长(从 145m 开始)。

这种情况正常吗?我对 Java 还很陌生,使用的版本是 Tomcat5.5。

6个回答

9
如果内存使用始终增长,那么就是内存泄漏。但是如果它增长到最大堆大小,然后下降,那么这是正常的垃圾回收行为。有许多工具可以帮助您了解更多信息。其中最简单的之一是连接JConsole(JDK的一部分)并随时间观察您的堆。
您还可以使用各种开关和参数(例如-verbose:gc)查看垃圾回收信息。
如果您想诊断内存泄漏,则有许多优秀的工具可用,包括几个免费的工具,适用于Eclipse、NetBeans、IntelliJ等IDE。

7
Sun "server" HotSpot 的默认行为是扩大堆而不清除用于缓存的 SoftReference。默认情况下,每兆最大堆大小可保留一秒钟。因此,堆将增长到最大大小。如果实际上出现内存不足的情况,或者性能变差(由于过多的 GC 或小型缓存),则需要查找内存泄漏。
另外,Tomcat 服务器经常在重新加载应用程序后出现内存泄漏问题。例如,Tomcat 在所有应用程序之间共享线程,这经常导致 Sun 的 ThreadLocal 实现不正确地保留值。

Tomcat不会泄漏,除非应用程序留下线程或在VM中安装钩子。 - Aaron Digulla
我稍微修改一下我的陈述。例如,Sun的ThreadLocal实现通常会导致泄漏,因为Tomcat不会丢弃线程。我不知道crazybob的Harmony实现会做什么。 - Tom Hawtin - tackline

4

我认为Tom Hawtin的回答是最好的。它会增长直到达到最大值,然后运行GC。在服务器环境下,这是有意义的:您需要最佳性能,而不是最佳内存使用率。您预计算出总内存量,然后给每个应用程序一个最大值,这样一切都适配并且具有最佳性能。此行为可以进行调整。

使用jconsole查看实际使用情况。进行GC并观察其降至何种程度。该数字不应随时间增长,否则您就会有内存泄漏。使用visualvm来调试内存泄漏。

每次重新加载应用程序时,它都会使用额外的Perm Gen内存,而这些内存无法被回收(在Sun JVM中,其他像JRockit这样的程序没有这个问题)。在生产环境中,您不应重新加载应用程序。每次重启Tomcat即可。如果您真的想继续这样做,则可以增加最大内存并使用标志-XX:MaxPermSize = 256m增加最大Perm Gen内存。


MaxPermSize正是我的问题所在。在开发过程中,我们不断部署更新版本的应用程序。 - Matthew Blackford

4
使用程序Lambda Probe,您可以轻松查看Tomcat中的内存使用情况(选项系统信息-内存利用率)。您可以在图表中看到Survivor Space Perm Gen Tenured Gen Eden Space Code Cache。
只需将此war文件部署到Tomcat并设置启动选项-Dcom.sun.management.jmxremote到Java启动即可。
现在,您可以看到内存的哪个部分增长。

1

这不是正常现象,很可能表明存在内存泄漏

您应该尝试使用内存分析器查看您的应用程序出现泄漏的位置。

通常,您应该寻找循环或重复操作,在这些操作中对象被创建但没有正确处理


这对于服务器JVM来说很正常。 - Sarel Botha
1
@sjbotha:持续增长绝对/不是/正常的。 - GEOCHET
我认为这取决于是否有无限制的持续增长。 - matt b

0

你可能有一个内存泄漏问题。我建议先连接jconsole到你的应用程序,确定是permgen空间还是堆内存,然后继续找出泄漏的位置。你能给我们更多信息吗?随着内存增长,你的应用程序发生了什么?

如果你对诊断这种问题相对较新,我建议使用jprofiler。你可以下载完全功能的试用版本,并拍摄内存快照以查看哪些对象在内存中。你可以使用这些信息来确定哪些对象是泄漏的源头。


这个应用程序已经运行多年了。最近,我发现这个问题,因为网站运行非常缓慢。我在想是否有人改变了配置。我不认为存在内存泄漏,因为没有人更改代码。 - user68461

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接