3

我有一个运行 tomcat7 的 linux (ubuntu) 服务器。服务器有 1GB 的内存,我收到了 java 抛出的堆空间错误。

基本上正在发生的事情是,我的 tomcat 服务器(运行我的 servlet 代码)正在抛出异常,因为没有更多的内存要分配。我的代码非常精简,所以我认为这不是问题。

当我查看 htop 时,我看到了很多 java 日志记录进程,我看到了大约 30 个这样的进程:

ps ax | grep java
 7412 pts/0    Sl     0:02 /usr/bin/java -Djava.util.logging.config.file=/usr/share/tomcat/apache-tomcat-7.0.29/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat/apache-tomcat-7.0.29/endorsed -classpath /usr/share/tomcat/apache-tomcat-7.0.29/bin/bootstrap.jar:/usr/share/tomcat/apache-tomcat-7.0.29/bin/tomcat-juli.jar -Dcatalina.base=/usr/share/tomcat/apache-tomcat-7.0.29 -Dcatalina.home=/usr/share/tomcat/apache-tomcat-7.0.29 -Djava.io.tmpdir=/usr/share/tomcat/apache-tomcat-7.0.29/temp org.apache.catalina.startup.Bootstrap start
 7426 pts/0    D+     0:00 grep --color=auto java
25937 ?        Sl    13:12 /usr/bin/java -Djava.util.logging.config.file=/usr/share/tomcat/apache-tomcat-7.0.29/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat/apache-tomcat-7.0.29/endorsed -classpath /usr/share/tomcat/apache-tomcat-7.0.29/bin/bootstrap.jar:/usr/share/tomcat/apache-tomcat-7.0.29/bin/tomcat-juli.jar -Dcatalina.base=/usr/share/tomcat/apache-tomcat-7.0.29 -Dcatalina.home=/usr/share/tomcat/apache-tomcat-7.0.29 -Djava.io.tmpdir=/usr/share/tomcat/apache-tomcat-7.0.29/temp org.apache.catalina.startup.Bootstrap start

随着时间的推移,这些 java 进程会慢慢泄漏内存,并且因为我只有 1gb 的 ram 可以使用我的 tomcat 服务器开始抛出堆空间异常。

我已经摆弄了 log4j(但它应该被关闭)并且我已经尽我所能关闭我能找到的配置中的日志记录。

任何帮助都会很棒,我只需要摆脱这些过程 - 它们是贪婪的方式。谢谢!

~ 丹

编辑:更多信息:

这可能是一个足够大的提示来完全解决这个问题 - 我检查了一些启动调试并想出了这个:

    Oct 02, 2012 8:50:08 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

SEVERE: The web application [/NMVServer] appears to have started a thread named [http-bio-8080-exec-53] but has failed to stop it. This is very likely to create a memory leak.
Oct 02, 2012 8:50:08 AM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads

SEVERE: The web application [/NMVServer] appears to have started a thread named [http-bio-8080-exec-54] but has failed to stop it. This is very likely to create a memory leak.
Oct 02, 2012 8:50:08 AM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads

SEVERE: The web application [/NMVServer] appears to have started a thread named [http-bio-8080-exec-62] but has failed to stop it. This is very likely to create a memory leak.
Oct 02, 2012 8:50:08 AM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads

SEVERE: The web application [/NMVServer] appears to have started a thread named [http-bio-8080-exec-64] but has failed to stop it. This is very likely to create a memory leak.

根据几个论坛,我发现的一个泄漏问题是由于 JDBC 驱动程序http://bugs.mysql.com/bug.php?id=36565的一个错误。这解决了我收到的另一条消息。

我一直在环顾四周,发现这非常有用:

http://wiki.apache.org/tomcat/MemoryLeakProtection

现在我只是想解决你所有的建议,谢谢!

~ 丹

4

2 回答 2

3

我一般希望java中的日志记录代码已经过很好的测试。如果您的日志配置没有生成日志输出,则开销较低。您的 htop 结果可能在 tomcat 中显示了一些空闲线程状态。

它可能正在记录,但您可能需要考虑您的应用程序或其他组件可能泄漏内存的所有方式

所有 JVM 都有非常好的诊断内存泄漏的工具。像这样的主题讨论了找出正在发生的事情的好方法。

编辑:更多的想法

如果有很多请求正在使用HttpServletRequest.getSession(). Manager组件配置进入Context内部,默认为 -1 表示无限会话。

如果您遇到已知的内存泄漏,请使用当前问题修复列表检查您的 tomcat 版本。

最后,Tomcat 7 包含一个JreMemoryLeakPreventionListener,它可能显示资源未释放。

于 2012-09-24T09:45:02.007 回答
1

Tomcat 通常有一个线程池。Java EE 规范要求启动一个单独的线程来处理每个 HTTP 请求。Tomcat 有一个线程池,并重用该池中的线程,而不是创建和终止它们。更多详细信息可在此处获得

您可以通过修改setenv.sh(或分别为 setenv.bat)设置 Tomcat 的最大内存限制,例如:

CATALINA_OPTS='-Xms512m -Xmx1024m'

有关 Oracle JVM 的更多详细信息,请参见此处

但实际上最重要的是跟踪 JVM 内部的内存分配。为此,您将需要Java VisualVM

于 2012-09-30T22:37:55.420 回答