我的任务是调试一个 Java (J2SE) 应用程序,该应用程序经过一段时间的活动开始抛出 OutOfMemory 异常。我是 Java 新手,但有编程经验。我很想听听您对诊断此类问题的好方法的看法?
到目前为止,我已经使用 JConsole 来了解正在发生的事情。我有一种预感,有些对象没有被正确释放,因此在垃圾收集期间没有被清理。
有没有我可以用来了解对象生态系统的工具?你会从哪里开始?
我的任务是调试一个 Java (J2SE) 应用程序,该应用程序经过一段时间的活动开始抛出 OutOfMemory 异常。我是 Java 新手,但有编程经验。我很想听听您对诊断此类问题的好方法的看法?
到目前为止,我已经使用 JConsole 来了解正在发生的事情。我有一种预感,有些对象没有被正确释放,因此在垃圾收集期间没有被清理。
有没有我可以用来了解对象生态系统的工具?你会从哪里开始?
我将从一个适当的 Java 分析器开始。JConsole 是免费的,但它的功能远不及花钱的那些。我使用了 JProfiler,物有所值。有关更多选项和意见,请参阅https://stackoverflow.com/questions/14762/please-recommend-a-java-profiler。
尝试使用Eclipse Memory Analyzer或任何其他可以处理 Java 堆转储的工具,然后使用在内存不足时生成堆转储的襟翼运行您的应用程序。
然后分析堆转储并查找可疑的高对象计数。
有关堆转储的更多信息,请参阅本文。
编辑:另外,请注意,您的应用程序可能只是合法地需要比您最初想象的更多的内存。您可以尝试首先将 java 最小和最大内存分配增加到更大的值,然后查看您的应用程序是否无限期地运行或只是稍微进一步。
最新版本的 Sun JDK 包括 VisualVM,它本身就是 Netbeans 分析器。它真的很好用。
http://www.yourkit.com/download/index.jsp是您需要的唯一工具。您可以在 (1) 应用程序启动时间和 (2) 在运行应用程序 N 时间后拍摄快照,然后比较快照以查看内存分配的位置。它还将在 OutOfMemoryError 上拍摄快照,以便您可以将此快照与 (1) 进行比较。
例如,我必须解决的最新项目抛出 OutOfMemoryError 异常,在启动 YourKit 后,我意识到大多数内存实际上被分配给了一些 ehcache “LFU” 类,关键是我们指定了某个 POJO 的负载缓存在内存中,但我们没有指定足够的 -Xms 和 -Xmx(启动和最大 JVM 内存分配)。
我也使用过 Linux 的vmstat,例如一些 Linux 平台没有启用足够的交换,或者没有分配连续的内存块,然后是jstat(与 JDK 捆绑在一起)。
更新见https://stackoverflow.com/questions/14762/please-recommend-a-java-profiler
您还可以将“UnhandledExceptionHandler”添加到应用程序的线程中。这将捕获“未捕获”异常,例如内存不足错误,并且您至少会知道异常是在哪里引发的。通常这不是问题,而是无法满足的“新”。作为一项规则,我总是将 UnhandledExceptionHandler 添加到线程中,如果没有其他需要添加日志记录的话。