我得到;Java HotSpot(TM)64位服务器VM警告:发生异常Java.lang.OutOfMemoryError,将信号SIGTERM发送到处理程序;tomcat中的错误

我得到;Java HotSpot(TM)64位服务器VM警告:发生异常Java.lang.OutOfMemoryError,将信号SIGTERM发送到处理程序;tomcat中的错误,java,tomcat7,out-of-memory,jvm-crash,Java,Tomcat7,Out Of Memory,Jvm Crash,我在VPS上有tomcat web应用程序,tomcat有时(大约每月一次)会在catalina.out中崩溃,并出现以下错误: Java HotSpot(TM)64位服务器VM警告:发生异常Java.lang.OutOfMemoryError,将信号SIGTERM发送到处理程序-可能需要强制终止VM 以下是有关我的配置的一些详细信息: VPS:debian-5.0-x86_64 内存:2.5 gb 虚拟处理器:8个 硬盘:60gb硬盘-70%免费 Tomcat 7.0 java-版本: ja

我在VPS上有tomcat web应用程序,tomcat有时(大约每月一次)会在catalina.out中崩溃,并出现以下错误:

Java HotSpot(TM)64位服务器VM警告:发生异常Java.lang.OutOfMemoryError,将信号SIGTERM发送到处理程序-可能需要强制终止VM

以下是有关我的配置的一些详细信息:

  • VPS:debian-5.0-x86_64

  • 内存:2.5 gb

  • 虚拟处理器:8个

  • 硬盘:60gb硬盘-70%免费

  • Tomcat 7.0

  • java-版本:

    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

我还在该服务器上安装了apachephp

我用Munin监控服务器负载,它告诉我内存和CPU使用率总是稳定的,在崩溃之前没有任何增加

我还通过java.lang.Runtime类记录了java内存使用情况,它显示jvm总是使用max200Mb内存,并且在崩溃之前没有增加。崩溃前的最后一个日志是40秒前,当时使用的内存是:152Mb

我的web应用程序还运行6-7个线程,从不同的公共API收集数据。这些线程在tomcat启动时启动,它们总是在周期性睡眠中运行

你能告诉我为什么它会崩溃吗?我怎样才能找到原因?

  • 从shell运行
    top
    ,查看Linux占用了多少内存 Java进程正在占用

  • 检查机器中的总体内存使用情况。可能是这样 其他进程正在消耗所有内存,迫使Linux停止运行 JVM:像Mysql或Postgress这样的数据库可能是一个可疑的对象

  • 在崩溃前后的时间段中检查
    /var/log/messages
    ,以了解 不寻常的事件


您可以编辑service.bat或service.sh文件(位于deistribution的bin文件夹中),并放置以下两个jvm参数

XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<PATH_TO_WRITE_DUMP>
XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=
指向写入转储的路径应具有必要的权限, 一旦您获得了堆转储文件(在OutOfMemory问题发生时将生成该文件),就可以手动或通过一些第三方工具对其进行分析。 您可以在jvisualvm中加载此文件并进行一些分析,也可以使用eclipse的内存分析器插件,它非常有用,并提供了一些潜在的内存泄漏怀疑和支配树(即,哪个对象支配堆)
这是一个很好的起点。

增加tomcat java启动内存,如: set JAVA_OPTS=-server-Xms256m-Xmx512m

让我们取消点击:

向处理程序发送信号SIGTERM时发生异常java.lang.OutOfMemoryError-可能需要强制终止VM

首先,它看起来像是发送给JVM(Tomcat)处理SIGTERM信号的东西。它必须是JVM之外的东西来实现这一点。JVM不向自己发送信号1

所以你需要弄清楚是什么在做这件事。我猜第一个猜测可能是OOM杀手。。。但是OOM杀手使用的是SIGKILL而不是SIGTERM。JVM永远也看不到SIGKILL的到来

(您可以通过查看“/var/log/messages”…或系统记录内核消息的任何地方来确认它不是OOM杀手。请参阅)

如果不是OOM杀手,那么有几种方法可以找到信号源:

一旦你找到了信号的来源,你就会知道它为什么会被发送


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


无论如何。在我看来,这似乎是一个常见Java问题的一个相当不寻常的表现。您的Tomcat中运行的webapps中很可能存在漏洞,导致内存泄漏。如果是这样的话,唯一真正的解决办法就是找到并修复bug。(增加堆大小…如果可能的话…只会推迟问题的发生。这可能会减少崩溃之间的间隔,但不太可能防止崩溃。)

假设您已准备好咬紧牙关:


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