Java 以编程方式检测内存泄漏
如果我故意创建了一个应用程序,在内存泄漏的情况下处理数据,我可以注意到,报告的内存如下:Java 以编程方式检测内存泄漏,java,memory-leaks,Java,Memory Leaks,如果我故意创建了一个应用程序,在内存泄漏的情况下处理数据,我可以注意到,报告的内存如下: Runtime.getRuntime().freeMemory() 开始在1到2 MB的可用内存之间振荡 然后,应用程序进入如下循环:GC,处理一些数据,GC,等等。但是由于GC经常发生,应用程序基本上不再做其他事情。甚至GUI也需要很长时间才能做出响应(不,我这里不是说EDT问题,实际上是虚拟机基本上陷入了无休止的GC’ing模式) 我想知道:有没有一种方法可以通过编程检测JVM没有足够的内存 请注意,
Runtime.getRuntime().freeMemory()
开始在1到2 MB的可用内存之间振荡
然后,应用程序进入如下循环:GC,处理一些数据,GC,等等。但是由于GC经常发生,应用程序基本上不再做其他事情。甚至GUI也需要很长时间才能做出响应(不,我这里不是说EDT问题,实际上是虚拟机基本上陷入了无休止的GC’ing模式)
我想知道:有没有一种方法可以通过编程检测JVM没有足够的内存
请注意,我不是在谈论内存错误的ouf,也不是在谈论检测内存泄漏本身
我说的是检测一个应用程序的内存太少,以至于它基本上一直在调用GC,几乎没有时间做其他事情(在我假设的示例中:处理数据)
例如,重复读取(比如)一分钟内的可用内存量,并查看该数字是否在不同值之间“振荡”,所有值均低于(比如)4MB,断定出现了一些漏洞,并且应用程序变得不可用?您可以将参数传递给java虚拟机,该虚拟机为您提供GC诊断,例如
-verbose:gc
此标志打开gc信息的日志记录。可用
在所有JVM中XX:+PrintGCTimeStamps
打印GCs发生的时间
相对于开始的
应用程序- 完全GC后,空闲堆与总堆的比率大于给定阈值,和/或
- 运行GC所花费的时间少于总时间的某个百分比
我发现允许您查看单个内存池(堆)的峰值使用情况,并设置阈值。然而,我从未尝试过这种方法,API中有很多提示表明并非所有JVM都实现完整的API。因此,我仍然推荐热点调优选项方法(见上文)而不是此方法。我看到了两种攻击向量 要么监视内存消耗 当您或多或少地经常使用大量可用内存时,很可能是内存泄漏(或者只是使用了太多内存)。虚拟机将不断尝试释放一些内存,但没有多大成功=>持续的高内存使用率 您需要将其与经常发生的大型之字形模式区分开来,而这并不是内存问题的指标。基本上,你会使用更多的内存,但是当gc找到时间做它的工作时,它会发现很多垃圾要带出来,所以一切都很好
另一个攻击向量是监视GC运行的频率和成功的种类。如果它经常运行,但内存增益很小,那么很可能您遇到了问题
我不知道你是否可以直接从你的程序中获取这类信息。但是,如果没有其他方法,我认为您可以在启动时指定参数,使gc日志信息变成一个文件,然后可以对其进行解析。您可以使用。您可以做的是生成一个线程,该线程会定期唤醒,并计算使用的内存量并记录结果。然后,您可以根据结果来估计应用程序中的内存增长率。如果您知道增长率和最大内存量,您可以(有信心地)预测应用程序何时会耗尽内存。我认为JVM正是为您这样做的,并抛出
java.lang.OutOfMemoryError:GC开销限制超过了。所以,若你们发现了OutOfMemoryError并检查了那个条消息,那个么你们就得到了你们想要的,不是吗
有关更多详细信息,请参阅。我一直在使用Plumber进行内存泄漏检测,这是一次很棒的体验,尽管许可证非常昂贵:我认为更好的办法是修复您的代码。@San Jacinto:您的评论目光短浅,很有吸引力,但这与此无关。如果你有什么有价值的东西要提供,你可能想重新阅读问题和答案。只有当你的代码出了问题时。并不是所有的第三方软件都是平等的,也不是一劳永逸的。我以为你可以插入一个GC钩子。。。让我想想……@马克·斯托尔:没错。。。而且,如果对我来说,这只是一个有趣的理论问题。