【问题标题】:Java Spring app + Tomcat: JVM doesn't make memory dumpJava Spring 应用程序 + Tomcat:JVM 不会进行内存转储
【发布时间】: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


【解决方案1】:

-XX:HeapDumpPath="/some/path/dump.out" 添加到您的 JVM 参数中,显式设置堆转储文件位置

【讨论】:

  • 好的,下次我们重新启动 Tomcat 时,我们将尝试显式设置转储的路径(但这对我来说似乎从来没有问题,因为在本地机器上,创建堆转储的位置也没有指定小路)。谢谢阿米尔
  • 你是对的,答案没有说明它是强制性的。在那种情况下,这个答案并不能解决问题。
  • 是的,我怀疑这不是路径问题,但我还是尝试指定它,但没有成功。不过谢谢。我在我的问题更新中描述了另一个测试。
  • 你在 JVM 参数@frankieta 中具体指定了什么?
  • @AmirAfghani 我的 JVM 参数与堆转储路径相同。具体来说:-....catalina 属性... -XX:PermSize=128m -XX:MaxPermSize=1024m -Xms1024m -Xmx6144m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="C:/" -Dcom.sun.management。 jmxremote.port=3333 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false 程序在我的 C 分区中写入转储时终止。这是控制台:java.lang.OutOfMemoryError: Java heap space Dumping heap to C:/\java_pid7996.hprof ...
猜你喜欢
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多