我在Tomcat中遇到了一个错误,提示为“Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler”。

10
我在VPS上运行了一个Tomcat Web应用程序,但有时(大约每月一次),Tomcat会崩溃,并在catalina.out中出现以下错误:

Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler- the VM may need to be forcibly terminated.

以下是关于我的配置的一些详细信息:
  • VPS:debian-5.0-x86_64

  • RAM:2.5 gb,

  • 虚拟处理器:8

  • HDD:60gb hdd - 70% free

  • Tomcat 7.0

  • java -version:

java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.13) (6b18-1.8.13-0+squeeze1)
OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)
  • Java参数:-Xms512m -Xmx1024m

  • 此外,我在该服务器上还安装了Apache-PHP。

    我正在使用Munin监视服务器负荷,它显示内存和CPU使用始终稳定,在崩溃之前没有任何增加。

    我还通过java.lang.Runtime类记录java内存使用情况,它显示jvm始终使用最大200Mb的内存,在崩溃之前没有任何增加。最后一次记录在崩溃前40秒,此时使用的内存为:152Mb。

    我的Web应用程序还运行6-7个线程,从不同的公共API收集数据。这些线程在tomcat启动时启动,并始终带有周期性的休眠。

    请问您能否告诉我为什么会崩溃?如何找到原因?

    4个回答

    2

    让我们来分析一下:

    异常java.lang.OutOfMemoryError在处理信号SIGTERM时发生- VM可能需要被强制终止。

    首先,看起来像是有些东西向JVM(Tomcat)进程发送了一个SIGTERM信号。 发送信号的肯定是JVM外部的某个东西。 一个JVM不会向自己发送信号1

    所以你需要找出是什么在这么做。 我最初的猜测可能是OOM killer ... 但OOM killer使用的是SIGKILL而不是SIGTERM。 JVM永远不会看到SIGKILL的到来!

    (您可以通过查看“/var/log/messages”或其他系统记录内核消息的地方来确认它不是OOM killer。请参见如何配置Linux Out-of-Memory Killer

    如果不是OOM killer,则有几种方法可以找到信号的源:

    一旦你找到了信号的来源,你将会有线索解释它为什么发送。


    另一件值得注意的事情是,OutOfMemoryError在处理SIGTERM时发生。 这强烈表明(对我来说)根本原因是有些东西检测到Tomcat使用了太多内存,并发送了一个SIGTERM使其消失(干净)。 我推断然后发生了什么是JVM向操作系统请求更多内存(以处理SIGTERM),而操作系统则回答“不”,因此JVM抛出了OutOfMemoryError。 不幸的是,JVM现在处于无法正常退出或恢复的状态。 因此,它说“VM可能需要被强制终止”。


    总之。 对我来说,这似乎是一个常见Java问题的相当不寻常的表现。 您很可能有一个在Tomcat运行的Web应用程序中泄漏内存的错误。 如果是这种情况,则唯一真正的解决方案是找到并修复错误。(如果可能,增加堆大小只是延迟问题。 它可能会减少崩溃之间的时间间隔,但不太可能防止它们。)

    假设您已准备好开始:


    1 - 除非某些东西在本地代码中做一些疯狂的事情...


    0
    • 在shell中运行top,查看Linux声称Java进程占用了多少内存。

    • 检查机器的整体内存使用情况。可能是其他进程消耗了所有内存,迫使Linux杀死JVM:像Mysql或Postgress这样的数据库是一个可能的嫌疑对象。

    • 检查崩溃周围时间段的/var/log/messages是否有异常事件。


    0

    增加Tomcat Java启动内存,例如: set JAVA_OPTS=-server -Xms256m -Xmx512m


    0

    您可以编辑service.bat或service.sh文件(在分发的bin文件夹中找到),并添加以下两个JVM参数:

    XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<PATH_TO_WRITE_DUMP>
    

    PATH_TO_WRITE_DUMP 应该具有必要的权限, 一旦出现 OutOfMemory 问题,将生成堆转储文件,请手动分析或使用某些第三方工具进行分析。 您可以在 jvisualvm 中加载此文件并进行一些分析,也可以使用 Eclipse 的 Memory-Analyzer-Plugin,它非常有用,并提供一些潜在的内存泄漏嫌疑对象和支配树(即哪个对象支配了堆) 这可以是一个很好的起点。


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