如何检测OutofMemoryError的原因?
我抱怨我的服务器应用程序在高负载时崩溃。
它是在Tomcat 5
运行的Web应用程序。
我看到线程转储,我发现有一个OutOfMemory错误
1TISIGINFO转储事件“systhrow”(00040000)详情
“java / lang / OutOfMemoryError”“无法创建线程:retVal -1073741830,errno 12”>收到1TIDATETIME日期:2012/07/17 at 20:03:17 1TIFILENAME> Javacore文件名:C:\ ServerApplication \ Tomcat5 \ bin \ javacore.34545719.4646464.4172.0003.txt
堆信息如下:
Maximum Java heap size : 1500m Initial Java heap size : 256m
这是初始和最大堆大小的配置(32位java)
我也看到有可用的堆空间
1STHEAPFREE Bytes of Heap Space Free: 2D19F3C0 1STHEAPALLOC Bytes of Heap Space Allocated: 5DC00000
这是750MB的免费空间,对吧?
从线程方法分析我看到Threads的数量是695
,其中49%
是java/lang/Object.wait(Native Method)
, 39%
是sun/misc/Unsafe.park(Native Method)
另外我看到这个NO JAVA STACK 1%
不确定这意味着什么。
0踏板也是死锁, 2%
是Runnable。
我不确定如何解释这些信息或如何从这里继续检测根本原因。
对此有何帮助?
根据这篇文章 :
java.lang.OutOfMemoryError有两个可能的原因:无法创建线程消息:
- 运行的线程太多,系统内部资源不足以创建新线程。
- 系统已用完本机内存以用于新线程。 线程需要内部JVM结构的本机内存,Java™堆栈和本机堆栈。
所以这个错误可能与内存完全无关,只是创建了太多的线程……
编辑:
由于你有695个线程,你需要695倍的堆栈大小作为内存。 考虑到关于线程限制的这篇文章 ,我怀疑你正在尝试为可用的虚拟内存空间创建太multithreading。
您应该使用-XX:+HeapDumpOnOutOfMemoryError
标志启动JVM。 生成OutOfMemoryError
时,这将生成堆转储。
然后,正如@Steve所说,你可以使用像MAT这样的工具来分析转储并查看分配了哪些对象,以及谁保留对它们的引用。 这通常可以让您深入了解JVM耗尽内存的原因。
我知道你的意思,找到某个地方可能会让人感到困惑。
看看Eclipse Memory Analyzer (MAT)。 它将使用JHat将程序的内存快照转储到一个文件中,您可以重新打开和分析该文件。
此文件的浏览器非常巧妙地概述了程序创建的所有对象,您可以查看各种级别以查找是否存在可疑内容。
附上我的评论以回答……
当您的可执行 webapp崩溃时,将其转储到MAT。 MAT会告诉你多次创建的对象。 如果它是一个自定义对象,它经常是,它很容易找到。 如果没有,你可以看到它的父母,截断它,并从那里运行(抱歉图形的例子,我现在并不完全专注于SO :)。
哦,我忘了提,你可以在几个条件下多次运行程序,并且每次都进行转储。 然后,您可以分析趋势的每个转储。
但在我的情况下,我应该使用什么?我有一个在Tomcat中运行的Web应用程序
对不起,也错了。 如果我没弄错的话,MAT会转储JVM 进程 ,因此只要VM在你的盒子上运行,你就可以转储它的进程,看看发生了什么。
另一条评论突变为部分解决方案……
这比实际上变得更加困难。 说真的,这很简单,在你运行MAT一两次之后就可以了解事情。 运行你的应用程序直到事情崩溃。 转发它。 改变些什么。 运行,崩溃,转储。 重复。 然后,在MAT中打开转储,并比较看起来可疑的内容。
我学习这个时最棘手的部分是找到要转储的进程ID – 这仍然不是太麻烦。
IBM WebSphere上的类似消息显示了这一行
“无法创建线程:retVal”
作为本机OOM的指示,这意味着某个(进程的)线程正在尝试请求堆上的大部分内存。
上面的IBM链接有一系列步骤 – 其中一些是IBM特定的。 看一看。
从本机内存使用角度来看:
- 最大Java堆设置
- JDBC驱动程序
- JNI代码或本机库
- 垃圾收集未使用的类。 确保未设置-Xnoclassgc。
- 线程池设置(固定大小的线程池)
- 太多的类加载器等,但这些并不常见。
- 来自javacores的类/类加载器的数量。
您可以看到的另一件事是PermGenSpace – 它有多大?
这个链接http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html建议
增加堆分配实际上会加剧这个问题! 它减少了编译器和其他本机组件必须使用的空间。 所以我的问题的解决方案是:1。减少分配给JVM的堆。 2.删除因未及时释放的本机对象而导致的内存泄漏。
您还在server.xml中为maxThreads配置了一个值吗? 默认值为200,但您的应用似乎有695?
固定
在创建新线程时遵循IBM技术说明java.lang.OutOfMemoryError ,特别是’ulimit’命令以增加默认值1024的值。
症状
[2/25/15 12:47:34:629 EST] 00000049 SystemErr R java.lang.OutOfMemoryError: Failed to create a thread: retVal -1073741830, errno 11 [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at java.lang.Thread.startImpl(Native Method) [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at java.lang.Thread.start(Thread.java:936) [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at org.eclipse.osgi.framework.internal.core.InternalSystemBundle.stop(InternalSystemBundle.java:251) [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at com.ibm.ws.runtime.component.RuntimeBundleActivator.shutdownEclipse(RuntimeBundleActivator.java:54) [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at com.ibm.ws.runtime.component.ServerCollaborator$ShutdownHook$1.run(ServerCollaborator.java:878) [2/25/15 12:47:34:630 EST] 00000049 SystemErr R at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:5459) [2/25/15 12:47:34:631 EST] 00000049 SystemErr R at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:5585) [2/25/15 12:47:34:631 EST] 00000049 SystemErr R at com.ibm.ws.runtime.component.ServerCollaborator$ShutdownHook.run(ServerCollaborator.java:850) [2/25/15 12:47:34:631 EST] 00000049 SystemErr R at com.ibm.ws.runtime.component.ServerCollaborator$StopAction.alarm(ServerCollaborator.java:809) [2/25/15 12:47:34:631 EST] 00000049 SystemErr R at com.ibm.ejs.util.am._Alarm.run(_Alarm.java:133) [2/25/15 12:47:34:631 EST] 00000049 SystemErr R at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1815)
环境
CentOS 6.6 64位IBM WAS 8.5.0.2 64位
参考
- 设置ulimits的准则(WebSphere Application Server)