【问题标题】:Out of Memory on Tomcat ShutdownTomcat 关闭时内存不足
【发布时间】:2011-12-16 21:38:24
【问题描述】:

我的问题的简短描述:我使用已部署的 Wicket 应用程序启动 Tomcat。当我想关闭 tomcat 时,我收到以下错误消息:

Error occurred during initialization of VM
 java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
at java.lang.ref.Reference.<clinit>(Reference.java:145)

我正在运行以下设置:

  • Ubuntu Linux:10.04(清醒),内核为 2.6.18-028stab094.3
  • Java 版本:“1.6.0_26”Java HotSpot(TM) 64 位服务器虚拟机
  • Tomcat 版本:7.0.23
  • jvm_args: -Xms512m -Xmx512m -XX:MaxPermSize=205m(这些是通过 CATALINA_OPTS 添加的,仅此而已)
  • 检票口 1.5.1
  • Tomcat 在子域上使用 ModProxy 配置了两个虚拟主机
  • 我的应用程序在 appbase 目录中部署为 ROOT.war(部署一个或两个应用程序没有区别)
  • '''没有部署应用程序不会导致关闭时 OOM''',除非我弄乱了 jvm 参数
  • war 的大小约为 500k,所有库都部署在 tomcat/common/lib 中(我在 conf/catalina.properties 中添加到 common.loader 的目录)
  • ulimit -u -> 无限制

当我检查 Tomcat 管理器应用程序时,它会显示以下关于 JVM 内存的信息:

Free memory: 470.70 MB Total memory: 490.68 MB Max memory: 490.68 MB
(http connector) Max threads: 200 Current thread count: 6 Current thread busy: 1

'top' 或 'free -m' 类似:

Mem:   2097152k total,  1326772k used,   770380k free,        0k buffers
20029 myuser   18   0  805m 240m  11m S    0 11.7   0:19.24 java  

我尝试启动 jmap 以获取堆转储,它也因 OutOfMemoryError 而失败。实际上,只要部署了我的一个或两个应用程序,任何其他 java 进程都会失败并出现相同的 OOM 错误(见顶部)。

在部署应用程序时出现问题。所以它有严重的问题。但是,该应用程序实际上运行平稳了很长一段时间。但是我在应用程序中也看到了OOM,所以我不相信冷静。

我的应用程序正在使用自定义过滤器类?会这样吗?

为了完整起见(希望如此),这是我的 common/lib 中的库列表:

activation-1.1.jar
antlr-2.7.6.jar
antlr-runtime-3.3.jar
asm-3.1.jar
asm-commons-3.1.jar
asm-tree-3.1.jar
c3p0-0.9.1.1.jar
commons-collections-3.1.jar
commons-email-1.2.jar
dependencies-provided.tgz
dom4j-1.6.1.jar
ejb3-persistence-1.0.2.GA.jar
geronimo-annotation_1.0_spec-1.1.1.jar
geronimo-jaspic_1.0_spec-1.0.jar
geronimo-jta_1.1_spec-1.1.1.jar
hibernate-annotations-3.4.0.GA.jar
hibernate-commons-annotations-3.1.0.GA.jar
hibernate-core-3.3.0.SP1.jar
hibernate-entitymanager-3.4.0.GA.jar
hibernate-search-3.1.0.GA.jar
javassist-3.4.GA.jar
joda-time-1.6.2.jar
jta-1.1.jar
log4j-1.2.16.jar
lombok-0.9.3.jar
lucene-core-2.4.0.jar
mail-1.4.1.jar
mysql-connector-java-5.1.14.jar
persistence-api-1.0.jar
quartz-2.1.1.jar
servlet-api-2.5.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
stringtemplate-4.0.2.jar
wicket-auth-roles-1.5.1.jar
wicket-core-1.5.1.jar
wicket-datetime-1.5.1.jar
wicket-extensions-1.5.1.jar
wicket-request-1.5.1.jar
wicket-util-1.5.1.jar
xml-apis-1.0.b2.jar

我很感激任何提示,甚至是推测,它们可以给我更多的想法来尝试什么。

更新:我进行了更多测试,发现此行为仅在部署我的一个或两个应用程序时发生。该行为不会发生在“空”tomcat 上(这是我弄乱 jvm args 的一个错误)

Update2:我目前正在尝试尝试在虚拟框中重现此行为,我想使用分析器对其进行调试。我仍然不相信在 2GB RAM 上运行我的设置是不可能的。

Update3 (10/01/12):我正在尝试运行 jenkins 而不是我自己的应用程序。相同的行为,所以肯定是服务器配置问题。调用 maven 时 Jenkins 作业失败,所以我什至不需要尝试下面建议的关闭黑客,因为在运行 Jenkins 时我需要第二个 java 进程。有人向我建议,因为这是一个虚拟服务器 ulimits 可能是从外部强加的,我将无法看到它们。我想我会就此提出一个新问题。谢谢大家。

Update4 (02/05/12):请参阅下面的包含提示的答案。我将在这里澄清更多:我现在 95% 确定错误发生是因为我达到了线程限制。但是,因为这是一个虚拟服务器,所以下面描述的方法无法检查这个值,因为它对 ulimit 不可见,这让我感到困惑,直到今天我才发现这是我可以看到的“numproc”值在我可以为我的虚拟服务器登录的 Parallels Power Panel 中。有 numproc 的资源警报,但直到现在我也没有看到这些。该值的硬限制为 96,我当然无法更改。 numproc 的当前值对应于我在切换“H”以查看线程后使用“top”看到的进程数。我很难找到这个,因为这个 numproc 值隐藏在面板的深处。遗憾的是,如果您想使用 apache 和 mysql 运行 Tomcat,那么 96 是一个相当低的数字。我也很难过,我什至在托管合同的小字中都找不到这个值,而且我敢说它与我的应用程序相当相关。所以我想我需要升级服务器。

感谢大家的帮助,最后每个人都帮助我找出问题所在。

【问题讨论】:

  • 如果在tomcat运行时在终端运行free -m会发生什么?
  • 另外,你有什么特别的 catalina_opts 吗?
  • jetty-all-server 对我来说似乎很奇怪。所有其他依赖似乎都很好,但是为什么要在 Tomcat 中嵌入码头(可能是 Wicket 需要,我不知道 Wicket)。
  • 啊,感谢您对码头的提示,该提示必须来自测试。我应该删除它。
  • 也许您可以使用 JVM 的 -XX:-HeapDumpOnOutOfMemoryError 选项获得堆转储:oracle.com/technetwork/java/javase/tech/…

标签: java tomcat memory-leaks wicket


【解决方案1】:

tomcat 关闭过程包括通过 tcp 端口向正在运行的 tomcat VM 发送命令/字。这个端口是在 server.xml 中配置的(如果我没记错的话,现在写在我的手机上)。到现在为止还挺好。

不幸的是,关闭脚本通过使用与 tomcat 相同的 java 选项启动一个 2. VM 来执行此操作。您的系统根本没有足够的内存来执行此操作。

作为一种解决方案,您可以使用 telnet 或其他方式编写自己的停止脚本。

如果需要,我可以稍后提供帮助。

希望对您有所帮助。 Viele grüsse Bert

【讨论】:

  • 这个想法很好,我不明白的是,在 2GB 的 RAM 上启动两个 java 进程是不可能的。甚至我的 Eclipse(我记得的最后一件事是基于 java 的)也不需要 1GB 左右,我的系统监视器告诉我。
  • 如果您的 Eclipse 不需要 2GB,那么您做错了 ;) 老实说:您只提供 XmX 和 PermGen 选项?您在顶部输出中看到的总和约为 800MB。不确定tomcat管理器报告的内存。它们与 top 的输出不一致。但最终,问题如上所述; tomcat 对运行配置使用与停止脚本相同的选项。
【解决方案2】:

看来你打开的线程太多了。

使用这个命令:

ulimit -u

结果如何? 应该是这样的:

max user processes (-u) 100

如果正确,您可以编辑此文件:

/etc/security/limits.conf

以及以下修改:

#<domain> <type> <item> <value>
user soft nproc 10000
user hard nproc 10000

【讨论】:

  • 谢谢。 ulimit -u 告诉我用户进程是无限的
  • 也许是另一个提示:添加 -Xss128k
  • 我从未停止学习。但遗憾的是,这并没有提供解决方案。 Tomcat Manager 告诉我反正运行的线程很少。
  • 谢谢,我终于找到你的答案是正确的。它不是很完美,因为 ulimit -u 没有告诉我这一点。我必须进入并行面板才能发现我的线程限制是 96,并且我在 tomcat、apache、mysql 上使用得非常快......
【解决方案3】:

你大概可以这样活一段时间。您需要做的就是在需要重新启动时终止 tomcat 进程。这不是一个好方法,但主要问题是您的应用程序是否正确运行。

但在我看来,从长远来看,您可能需要订购具有更多可用 RAM 的托管计划。

【讨论】:

  • 我正在尝试检查是否确实如此 - 尽管系统似乎告诉我有足够的 RAM。所以我试图在我的开发机器上运行设置,但设置需要一些时间才能在这里重现。
  • 几个月前我在使用 Struts2 和 GWT 应用程序时遇到了类似的情况,每当我需要停止服务器时,我不得不杀死 Tomcat 大约三周,这种情况并不常见。幸运的是应用程序运行良好。
  • 应用程序有时也会崩溃。这也是一个相当小的应用程序。我似乎无法获得内存消耗的真实数量。我说的所有数字都说“没关系”,但例外情况都说不是。
【解决方案4】:

就在上周,我在安装 tomcat 时遇到了类似的问题。我设法通过给 tomcat 一个较小的堆来解决它。像这样的:

export CATALINA_OPTS=”-Xms256m -Xmx512m”

在启动 Tomcat 之前可能会有所帮助。与此同时,你必须用老式的方式杀死它,kill -9 ;)

编辑:你也可以看看here,看来tomcat会自动创建一堆“备用”线程,但你可以限制这些以及配置中的最大线程数。希望对您有所帮助。

【讨论】:

  • 有趣的是,现在的行为有点不同了。我将对此进行更多实验。
  • 很高兴能提供帮助,看看我刚刚发布的编辑,可能是你的问题是默认的“备用”线程数。
  • 那个链接很好。没有为这个特定问题提供解决方案,但很好地提醒了未来可能出现的问题。
猜你喜欢
  • 1970-01-01
  • 2016-09-27
  • 2013-12-24
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-04
  • 1970-01-01
相关资源
最近更新 更多