java - 以编程方式检测内存泄漏

标签 java memory-leaks

如果我故意创建一个处理数据的应用程序,同时遭受内存泄漏,我会注意到报告的内存,比如:

Runtime.getRuntime().freeMemory()

开始在 1 到 2 MB 的可用内存之间波动。

然后应用程序进入这样一个循环:GC,处理一些数据,GC,等等。但是因为 GC 发生得如此频繁,应用程序基本上不再做其他事情了。甚至 GUI 也需要很长时间才能做出响应(而且,不,我在这里不是在谈论 EDT 问题,这实际上是 VM 基本上陷入了某种无休止的 GC 模式)。

我想知道:有没有办法以编程方式检测 JVM 不再有足够的内存?

请注意,我不是在谈论 ouf-of-memory 错误,也不是在检测内存泄漏本身。

我说的是检测应用程序运行时内存太低,以至于它基本上一直在调用 GC,几乎没有时间做其他事情(在我假设的例子中:处理数据)。

例如,重复读取在一分钟内有多少内存可用,然后查看该数字是否一直在低于不同值(例如 4 MB)之间“振荡”,是否可以得出结论:是否存在泄漏,应用程序已无法使用?

最佳答案

And I was wondering: is there a way to programmatically detect that the JVM doesn't have enough memory anymore?

我不这么认为。您可以大致了解在任何给定时刻有多少堆内存可用,但据我所知,您无法可靠地确定何时内存不足。 (当然,你可以做一些事情,比如抓取 GC 日志文件,或者尝试在空闲内存振荡中挑选模式。但这些在 JVM 变化面前可能是不可靠和脆弱的。)

但是,还有另一种(IMO 更好的)方法。

在 Hotspot 的最新版本中(我相信是 1.6 版及更高版本),您可以调整 JVM/GC,以便它更快地放弃并抛出 OOME。具体来说,JVM 可以配置为检查:

  • 在完整 GC 之后,空闲堆与总堆的比率大于给定阈值,和/或
  • 运行 GC 所花费的时间少于总时间的特定百分比。

相关的 JVM 参数是“UseGCOverheadLimit”、“GCTimeLimit”和“GCHeapFreeLimit”。不幸的是,Hotspot 的调整参数在公共(public)网络上没有很好的记录,但这些都列出了 here .

假设您希望您的应用程序做一些明智的事情……当它没有足够的内存来正常运行时就放弃……然后只需启动具有比“GCTimeLimitor”或“GCHeapFreeLimit”更小的默认值。

编辑

我发现 MemoryPoolMXBean API允许您查看单个内存池(堆)的峰值使用情况,并设置阈值。然而,我从来没有尝试过这个,并且 API 有很多提示表明并非所有 JVM 都实现了完整的 API。因此,我仍然会推荐 HotSpot 调整选项方法(见上文)而不是这个方法。

关于java - 以编程方式检测内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4272541/

相关文章:

java - Spring Boot 访问静态资源缺少 scr/main/resources

iPhone App - 内存警告后背景消失

powershell - 在远程计算机上运行 Invoke-Command 时出现 OutOfMemory 错误

java - 无法找到或加载主类: Executable JAR from Maven

与自定义密码套件的 Java HTTPS 连接

Java光滑的命令行应用程序?

ios - 在两个局部变量之间的仪器中检测到泄漏

java - 使用类型转换添加字节,Java

node.js - 这是内存泄漏吗?

ios - iPhone 内存警告和崩溃 - 但仪器显示低内存使用