如何检测内存不足的情况?

Posted

技术标签:

【中文标题】如何检测内存不足的情况?【英文标题】:How to detect Out Of Memory condition? 【发布时间】:2010-11-22 13:13:18 【问题描述】:

我有一个在 Websphere Application Server 6.0 上运行的应用程序,由于内存不足,它几乎每天都会崩溃。从详细的 GC 可以确定存在内存泄漏(其中很多)

不幸的是,该应用程序是由外部供应商提供的,修复问题是一个缓慢而痛苦的过程。作为该过程的一部分,我需要在每次发生 OOM 时收集日志和堆转储。

现在我正在寻找一些方法来实现它的自动化。根本问题是如何检测 OOM 状况。一种方法是创建将定期搜索新堆转储的 shell 脚本。这种方法让我觉得有点脏。另一种方法可能是以某种方式利用 JMX。但我在这方面的经验很少或根本没有,也不知道该怎么做。

或者在 WAS 中是否为此设置了某种触发器/挂钩?非常感谢您的每一个建议!

【问题讨论】:

【参考方案1】:

如果您希望自动进行堆转储,我看到了两个选项,但 @Mark's solution 在 OOM 上进行堆转储并不令人满意。

    您可以使用MemoryMXBean 检测高内存压力,然后使用programmatically create a heap dump 如果使用(或使用增量)似乎很高。 您可以使用jmap 定期获取内存使用信息并使用 cron 的 shell 脚本生成堆转储(本地和远程均可)。

如果您可以在 OOM 上进行回调,那就太好了,但是,嗯,该回调可能会因 OOM 错误而崩溃。 :)

【讨论】:

【参考方案2】:

应该可以编写一个简单的程序从内核中获取进程列表并扫描它以查看您的 WAS 进程是否仍在运行。在 Unix 机器上,你可能会在几分钟内用 Perl 写出一些东西(如果你知道 Perl),但不确定在 Windows 下会有多困难。每五分钟左右将其作为计划任务运行一次,如果该进程未显示,您可以让它分叉另一个处理堆转储的进程并重新启动 WAS。

【讨论】:

【参考方案3】:

从监控的角度来看,我们在 ITCAM 方面的经验并不出色。我们放弃了它,转而支持 CA Wily Introscope。

【讨论】:

【参考方案4】:

我认为当 OOM 发生时您需要堆转储。随着时间的推移定期收集信息应该可以了解正在发生的事情。

正如已经观察到的那样,存在各种用于分析这些问题的工具。我在 ITCAM for WebSphere 上取得了成功,作为一名 IBM 员工,我可以随时访问它。我们很快就能够在出现问题的情况下识别出确切的代码行。

如果您有任何方法可以获得这种性质的工具,那么这就是您要走的路。

【讨论】:

【参考方案5】:

您看过最新 Java 6 JDK 中的 jvisualvm 工具吗?

它非常适合检查正在运行的代码。

【讨论】:

【参考方案6】:

你看过JConsole 吗?它使用 JMX 让您可以查看各种 JVM 指标,包括内存信息。可能值得一开始就使用它来监视您的应用程序,以了解内存的消耗方式/时间。您可能会发现内存在一天中被均匀消耗,或者在使用某些功能时。

看看上面链接的detecting low memory部分。

如果您需要,您可以编写JMX client 来自动观察应用程序并触发所需的任何操作。 JConsole 将指示您需要轮询哪些 JMX 方法。

【讨论】:

【参考方案7】:

您可以在启动时将以下参数传递给 JVM,并且会在 OutOfMemoryError 上自动生成堆转储。第二个参数允许您指定堆转储文件的路径。通过使用它,您至少可以检查特定文件是否存在,以查看是否发生了堆转储。

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

【讨论】:

谢谢。我正在使用它,但我需要某种关于 heapdump 已创建的通知。而且我正在寻找比定期扫描文件系统更好的方法。 我更新了我的答案,因此您只需要检查特定文件是否存在。我不确定是否有更好的方法。 只要用这样的东西来通知你:-XX:OnOutOfMemoryError="echo PID %p has just generated a heapdump | mail admin@admin.com" 给你发邮件或运行你想要的任何命令通知你。【参考方案8】:

您可以添加一个侦听器(会话范围或应用程序范围属性侦听器)类,每次在会话/应用范围中添加新对象时都会调用该类。

在此 - 您可以尝试检查应用程序使用的总内存(记录它)作为调用 run gc(请注意,调用它并不意味着 gc 将始终运行)

(以上是基于使用增长的日志部分和gc)

对于预定的 gc: 此外,您可以保留一个计时器任务类,每隔几个小时运行一次并请求 gc。

【讨论】:

感谢您的回答。不幸的是,如果存在内存泄漏(=对对象的不需要的引用),运行 GC 将无济于事。从详细 GC 图中,我可以看到垃圾收集器在 OOM 之前经常被触发。 在这种情况下,如果您知道其他未使用的活动对象,您可以在定义的时间段后将它们从范围(应用程序/会话)中删除。【参考方案9】:

如果您乐观地认为它可以存活 12 小时,那么您可以像每天晚上一样编写受控重启脚本,而不是等到应用程序崩溃。

也许甚至 websphere 也可以为您做到这一点!?

【讨论】:

嗯,这将在短期内帮助我。另一方面,我需要修复泄漏。这种方法会阻止我在发生 OOM 时收集日志。 啊,我以为您只需要等到您的外部供应商解决了问题...当然,如果您需要哈希转储进行报告,那就是另一回事了 :)

以上是关于如何检测内存不足的情况?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone - 如何处理内存不足的情况

在 Windows 上分配开始失败之前检测内存运行不足

内存不足怎么办

如何在不因内存不足而导致应用程序崩溃的情况下擦除矢量元素?

电脑上看图片显示内存不足

startActivityForResult() 在内存不足的情况下