我在 tomcat 中收到“Java HotSpot(TM) 64 位服务器 VM 警告:异常 java.lang.OutOfMemoryError 发生分派信号 SIGTERM 到处理程序”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11095094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:45:24  来源:igfitidea点击:

I get "Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler" error in tomcat

javatomcat7out-of-memoryjvm-crash

提问by Arshak

I have tomcat web app on VPS and the tomcat sometimes (about once a month) crashes with the following error in catalina.out:

我在 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.

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

Here are some details about my configuration:

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

  • VPS: debian-5.0-x86_64

  • RAM: 2.5 gb,

  • virtual processors: 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 params: -Xms512m -Xmx1024m

  • VPS: debian-5.0-x86_64

  • 内存:2.5 GB,

  • 虚拟处理器:8

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

  • 雄猫 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

I have also Apache-PHP on that server.

我在该服务器上也有 Apache-PHP。

I'm monitoring server load with Munin and it shows me that memory and CPU usage is always stable and there were no any increases before crash.

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

I'm also logging java memory usage via java.lang.Runtime class, and it shows that jvm always uses max200Mb memory and there were no increase before crash. The last log before crash was 40 seconds ago and that time used memory was: 152Mb.

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

My web app also runs 6-7 threads that collecting data from different public APIs. These threads start when tomcat is starting, and they always running with periodic sleeps.

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

Can you please tell me why it crashes? How can I find the reason?

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

回答by Stephen C

Lets unpick this:

让我们解开这个:

Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler- the VM may need to be forcibly terminated.

异常 java.lang.OutOfMemoryError 发生分派信号 SIGTERM 到处理程序 - 可能需要强制终止 VM。

First of all, it looks like something sent the JVM (Tomcat) process a SIGTERM signal. It has to be something external to the JVM that did that. A JVM doesn't send signals to itself1.

首先,看起来有些东西向 JVM (Tomcat) 进程发送了一个 SIGTERM 信号。它必须是 JVM 外部的东西才能做到这一点。JVM 不会向自身发送信号1

So you need to figure out what is doing that. My guess first guess would be the OOM killer ... but the OOM killer uses SIGKILL not SIGTERM. And the JVM never sees the SIGKILL coming!

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

(You can confirm that it is not the OOM killer by looking in "/var/log/messages" ... or wherever your system logs kernel messages. See How to Configure the Linux Out-of-Memory Killer)

(您可以通过查看“/var/log/messages”...或系统记录内核消息的任何位置来确认它不是 OOM 杀手。请参阅如何配置 Linux 内存不足杀手

If it is not the OOM killer, then there are a few ways to find the source of a signal:

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

And once you have the source of the signal, you will have clues as to why it was sent.

一旦你掌握了信号的来源,你就会知道为什么发送信号。



The other noteworthy thing is that the OutOfMemoryErroroccurred while handling the SIGTERM. This strongly suggests (to me) that the root cause is that something has detected that Tomcat is using too much memory, and has sent it a SIGTERM to make it go away (cleanly). I surmise that what happens then is that the JVM goes to the OS to ask for a little bit more memory (to handle the SIGTERM) and the OS says "No", and the JVM throws an OutOfMemoryError. Unfortunately, the JVM is now in a state where it cannot either exit cleanly or recover. Hence it says "the VM may need to be forcibly terminated".

另一个值得注意的事情是OutOfMemoryError在处理 SIGTERM 时发生的。这强烈暗示(对我而言)根本原因是某些东西检测到 Tomcat 使用了过多的内存,并向它发送了一个 SIGTERM 以使其消失(干净地)。我猜测接下来会发生什么是 JVM 去​​操作系统请求更多的内存(以处理 SIGTERM)并且操作系统说“不”,并且 JVM 抛出一个OutOfMemoryError. 不幸的是,JVM 现在处于既不能干净退出也不能恢复的状态。因此它说“可能需要强行终止虚拟机”。



Anyhow. This looks to me like a rather unusual manifestation of a common Java problem. You most likely have a bug in the webapps running in your Tomcat that is leaking memory. If that is the case, the only real solution is to find and fix the bug. (Increasing the heap size ... if possible ... only puts the problem off. It may decrease the interval between crashes, but it is unlikely to prevent them.)

无论如何。在我看来,这像是常见 Java 问题的一种相当不寻常的表现。您很可能在 Tomcat 中运行的 web 应用程序中存在内存泄漏的错误。如果是这种情况,唯一真正的解决方案是找到并修复错误。(增加堆大小......如果可能的话......只会解决问题。它可能会减少崩溃之间的间隔,但不太可能阻止它们。)

Assuming that you are ready to bite the bullet:

假设您已准备好硬着头皮:



1 - Unless something is doing something nutty in native code ...

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

回答by Adi Dembak

  • Run topfrom the shell and see how much memory Linux claims the Java process is taking up.

  • Check the overall memory usage in the machine. It could be that other processes are consuming all the memory, forcing Linux to kill the JVM: A database such as Mysql or Postgress is a likely suspect.

  • Check /var/log/messagesin the time periods around the crashes for unusual events.

  • top从 shell运行并查看 Linux 声称 Java 进程占用了多少内存。

  • 检查机器中的整体内存使用情况。可能是其他进程正在消耗所有内存,迫使 Linux 终止 JVM:Mysql 或 Postgress 等数据库可能是可疑的。

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

回答by TruckDriver

You can edit the service.bat or service.sh file(found in bin folder of deistribution) and put the below two jvm parameters

您可以编辑 service.bat 或 service.sh 文件(在 deistribution 的 bin 文件夹中找到)并输入以下两个 jvm 参数

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

The PATH_TO_WRITE_DUMP should have necessary permissions, Once you get the heap dump file which will be generated in case of an OutOfMemory issue, analyze it either by hand or by some third party tools. You can load this file in jvisualvm and do some analysis or you can use Memory-Analyzer-Plugin of eclipse , it's very useful and gives some potential memory leak suspects and dominator trees (i.e. which object dominates the heap) This can be a good starting point.

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

回答by Wei Kleeff

increase you tomcat java startup memory, like: set JAVA_OPTS=-server -Xms256m -Xmx512m

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