Java服务器应用程序中的内存泄漏

35 浏览
0 Comments

Java服务器应用程序中的内存泄漏

如何在Java中找出内存泄漏(例如使用JHat)?我尝试在JHat中加载堆转储以进行基本查看,但是我不明白我应该如何找到根引用(参考)或者叫什么名字。基本上,我可以看到有几百兆字节的哈希表条目([java.util.HashMap$Entry或类似的东西),但是地图在各个地方都被使用...是否有一种方法可以搜索大型地图,或者找到大型对象树的一般根?\n[编辑]\n好的,我已经阅读了到目前为止的答案,但是让我们假设我是一个吝啬鬼(意思是我更感兴趣学习如何使用JHat而不是支付JProfiler的费用)。而且,由于它是JDK的一部分,JHat始终可用。除非当然JHat只能使用暴力破解,但我不相信这可能是情况。\n此外,我不认为我能够实际修改(添加所有地图大小的日志记录)并运行足够长的时间以便我注意到泄漏。

0
0 Comments

在我的Java服务器应用程序中出现了内存泄漏问题。出现这个问题的原因可能是堆转储文件太大,导致工具崩溃,或者在只能访问shell的某些生产环境中进行故障排除。为了解决这个问题,我们可以利用hprof转储文件。

首先,我们可以查找"SITES BEGIN",这将显示占用最多内存的对象。每个条目还包括一个“trace” ID,我们可以搜索该“TRACE nnnn”以查看分配对象的前几个栈帧。通常,一旦找到对象的分配位置,就可以发现错误并解决问题。此外,我们还可以通过-Xrunhprof选项来控制记录在堆栈中的帧数。

如果检查分配位置,并没有发现任何问题,那么我们需要从一些活动对象向根对象进行反向链接,以查找意外的引用链。虽然工具非常有帮助,但我们也可以通过手动(或使用grep命令)进行相同的操作。根对象不止一个,线程、类和堆栈帧都可以作为根对象,并且它们所引用的任何对象都不会被垃圾回收。

为了进行反向链接,我们可以在堆转储文件的HEAP DUMP部分查找具有错误跟踪ID的条目。这将带我们到一个OBJ或ARR条目,其中显示了一个十六进制的唯一对象标识符。通过搜索该标识符的所有出现,我们可以找到对该对象有强引用的对象。然后,我们可以沿着每条路径向后追溯,直到找到内存泄漏的位置。正因为如此,工具非常方便。

静态成员常常导致内存泄漏问题。实际上,即使没有工具,花几分钟的时间检查代码中的静态Map成员也是值得的。Map是否会变得很大?是否有任何清理Map条目的操作?

最后,提到了一些工具的问题。据我了解,jhat和MAT尝试将整个堆转储加载到内存中,因此在处理大型堆转储时(即最需要进行堆分析的应用程序),通常会发生OutOfMemoryError并崩溃。NetBeans Profiler似乎使用了不同的引用索引算法,它在处理大型堆转储时可能会变慢,但至少不会在工具中消耗无限的内存并崩溃。

0
0 Comments

在我Java服务器应用程序中出现了内存泄漏的问题。这个问题的原因是由于没有一个能在点击后不用等待5分钟的工具来找出潜在的内存泄漏,因此很难发现问题。

有人建议我使用几种工具(我只尝试了JDK中的Visual WM和JProbe试用版),因此我建议使用一个建立在Eclipse平台上的免费/开源工具,内存分析器(有时也称为SAP内存分析器),可以在http://www.eclipse.org/mat/上找到。

这个工具非常酷的地方在于,它在我第一次打开它时对堆转储进行了索引,这使得它可以显示像保留堆这样的数据,而不需要等待每个对象5分钟(几乎所有操作都比我尝试过的其他工具快得多)。

当您打开堆转储时,第一个屏幕会显示一个饼图,其中包含最大的对象(计算保留堆),您可以快速导航到对您来说太大的对象。它还有一个查找可能的内存泄漏嫌疑对象的功能,我认为这可能很方便,但由于导航已经足够我使用了,所以我没有深入研究它。

值得注意的是:显然,在Java 5及以上版本中,HeapDumpOnCtrlBreak VM参数不可用。我找到的解决方法(到目前为止,还在寻找中)是使用JMap将.hprof文件转储出来,然后将其放入Eclipse并使用MAT进行检查。

关于获取堆转储,大多数分析工具(包括JVisualVM)都包括将堆和线程转储到文件的选项。

0
0 Comments

在我的Java服务器应用程序中出现了内存泄漏问题。内存泄漏是指应用程序中的一些对象被分配了内存空间,但在使用完之后没有被正确释放,导致内存占用不断增加,最终导致应用程序崩溃或性能下降。

内存泄漏的原因可能是代码中存在逻辑错误,导致某些对象无法被垃圾回收器正确回收,或者存在循环引用等情况。为了解决内存泄漏问题,可以采取以下方法:

1. 使用专门的工具进行内存泄漏分析,例如jProfiler。这类工具可以生成内存快照,并提供图形化界面进行分析。

2. 启动应用程序,等待其进入稳定状态,即完成所有初始化并处于空闲状态。

3. 运行可能导致内存泄漏的操作,多次运行以确保缓存、数据库等初始化操作完成。

4. 运行垃圾回收器(GC)并生成内存快照。

5. 再次运行该操作。根据操作的复杂性和数据的大小,可能需要多次运行。

6. 再次运行垃圾回收器并生成内存快照。

7. 对比两个内存快照,并进行分析。从正差值最大的对象类型开始,找出导致这些额外对象占用内存的原因。

对于处理多线程请求的Web应用程序,分析会更加复杂,但基本的分析方法仍然适用。

除了使用专门的工具外,还可以通过调用System.gc()方法触发垃圾回收器的运行。但需要注意的是,虚拟机(JVM)可能会选择忽略这个调用,具体取决于JVM的实现。

关于内存快照,它是指在某个时间点上,应用程序中所有对象的状态的拷贝。通过分析内存快照,可以得到代码中各种对象类型的数量。

要找出导致对象占用内存的原因,可以从正差值最大的对象类型开始分析。通过查看代码,可以确定这些对象是在哪些地方创建的,以及它们是否被正确释放。可以使用调试工具或添加日志语句来追踪对象的创建和销毁过程。

总之,通过使用专门的工具进行内存分析,结合代码审查和调试技巧,可以找出并解决Java服务器应用程序中的内存泄漏问题。

0