【问题标题】:tomcat java.util.logging processtomcat java.util.logging 进程
【发布时间】:2012-08-13 08:53:47
【问题描述】:

我有一个运行 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

现在我正在努力解决您的所有建议,谢谢!

~丹

【问题讨论】:

  • 请运行ps ax | grep java 并粘贴一个完整命令行。您粘贴的部分仅显示了一堆配置选项。实际调用的类是不可见的...
  • 抱歉延迟和狡猾的初始帖子。我已经用正确的信息更新了它。
  • 您的意思是您的帖子中大约有 30 个进程与 pid 为 7412 的进程相似?但该进程代表了整个 Tomcat 服务器,从“org.apache.catalina.startup.Bootstrap start”可以看出。这意味着您有 30 台服务器正在运行?
  • 对不起,这有点模棱两可,我认为更多的是 htop 对正在运行的进程的解释,{ps ax} 更准确。我认为它只有一个进程是 JVM 的引导程序

标签: unix memory-leaks log4j tomcat7 servlet-3.0


【解决方案1】:

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

它可能正在记录,但您可能需要考虑all the ways your application or another component may be leaking memory

所有 JVM 都有很好的诊断内存泄漏的工具。 this 之类的主题讨论了找出正在发生的事情的好方法。

编辑:更多想法

如果大量请求使用HttpServletRequest.getSession(),您可能需要检查配置是否有太多会话。 Manager 组件配置位于 Context 内部,默认为 -1 表示无限会话。

使用the current issue fix list 检查您的tomcat 版本,以防您遇到已知的内存泄漏。

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

【讨论】:

  • 谢谢,这给了我一个很好的起点。我知道有几种方法可以欺骗垃圾收集器(可以这么说)——我已经开始调查我的 mysql-connector 池并查看其他区域。感谢您的建议。
  • P.S.有什么特别的关于小服务程序和大量使用“doPost”例程的吗?
  • 通常 doPost() 是无状态的,不应持有任何连接或创建任何永久对象。重载应该没关系。
【解决方案2】:

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

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

CATALINA_OPTS='-Xms512m -Xmx1024m'

有关 Oracle JVM 的更多详细信息,请访问here

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

【讨论】:

    猜你喜欢
    • 2013-01-13
    • 2012-02-26
    • 2015-05-13
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 2020-10-22
    • 2013-04-03
    • 2023-03-22
    相关资源
    最近更新 更多