【发布时间】:2015-02-21 09:11:34
【问题描述】:
在我的公司中,我们在 Spring(Flex 前端)中开发了一个企业 Web 应用程序,并在 Tomcat 6 中以 SAAS 样式将该应用程序部署给我们的客户。
最近我们遇到了(看似)随机的 OutOfMemory 错误,所以经过调查,我知道我们应该在错误发生时检查 JVM 的内存转储。
我们使用的JVM是1.6.18,Tomcat版本是Windows Server 2008下的Tomcat 7.0.23。
我在 Tomcat 监控面板(在 Java 选项卡下)添加了参数 -XX:+HeapDumpOnOutOfMemoryError,但机器没有产生任何转储。
在我们正在调查的服务器上,完整的 java 选项设置如下:
-Dcatalina.home=C:\Program Files\Apache Software Foundation\Tomcat 7.0
-Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 7.0
-Djava.endorsed.dirs=C:\Program Files\Apache Software Foundation\Tomcat 7.0\endorsed
-Djava.io.tmpdir=C:\Program Files\Apache Software Foundation\Tomcat 7.0\temp
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=C:\Program Files\Apache Software Foundation\Tomcat 7.0\conf\logging.properties
-XX:PermSize=128m
-XX:MaxPermSize=1024m
-Xms1024m
-Xmx6144m
-XX:+HeapDumpOnOutOfMemoryError
-Dcom.sun.management.jmxremote.port=3333
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
正如您所见,最大堆大小非常大(6 Gigs),因为 out 应用程序特别重。 出于测试原因,我添加了 jmx 参数,以便使用 VisualVM 实时查看 JVM 状态,但在查看时没有发生任何事情。
stderr 显示的就是这个:
java.lang.OutOfMemoryError
在它之前什么都没有(除了我不知道是否相关的其他错误,但它们是在 OOM 之前的几小时或几分钟内记录的),之后什么都没有。
它不报告内存部分(Java 堆大小或 Permgen 空间)对我来说似乎很奇怪。
也许保留的内存堆太大,JVM 无法写入,因为它处于临界状态 (OOM)? 也许是 JMX 参数搞砸了?
这是当前运行的 JVM 的 VisualVM 截图:
更新:
我安装在另一个 tomcat 安装上(与问题所在的版本相同,相同的 java 选项)相同的 Web 应用程序被修改为通过无限地填充 arraylist 来手动引发 OOM环形。 测试证明 java 选项 -XX:+HeapDumpOnOutOfMemoryError 有效,因为在我引发 OOM 后产生了内存转储;但是在这种情况下,错误是:
java.lang.OutOfMemoryError: Java Heap space
跟随堆栈跟踪。 因此,问题似乎不在于我的 JVM args 表示法,而在于我遇到的特定类型的错误。
另一个特点是,在我的测试中抛出 OOM 错误后,该应用程序继续在 Tomcat 中运行。另一方面,我原来的问题中的 OOM 导致 Tomcat 服务停止。
遗憾的是,在它停止之前没有进行堆栈跟踪,看起来很难进一步调查。 :(
【问题讨论】:
-
为什么不使用 jvisualVm 创建内存转储? (您可以使用 MAT 研究内存转储中的泄漏 - 它是免费的)或者当您将应用程序部署在 tomcat 上时使用它并在关闭和打开它时监视应用程序,这样您可以查看所有线程是否是否关闭。
-
@aurelius 感谢您的评论。我目前正在使用 VisualVM,我知道我可以从中进行转储,但是我想要的是在 OOM 发生时进行转储(我认为 -XX:+HeapDumpOnOutOfMemoryError 选项应该这样做)。几天前,我尝试使用 VisualVM 进行转储并使用 MAT 进行查看,但没有成功(我补充说,我不知道在分析转储时确切在哪里查看,我通常查看可疑的内存泄漏和 Dominator树)
-
很确定你已经检查过了,但还是会说:你的磁盘上是否有空间(大约 6 GB)用于堆转储?
-
是的@Khanna111GauravKhanna,有足够的空间:)
标签: java tomcat jvm out-of-memory dump