我认为我有内存泄漏 (他们说第一步是承认问题,对吗?)
无论如何,我想我会这样做 - 按区域查看堆的附加图像:。 绿色是伊甸园,蓝色/红色是S0 / S1,紫色是老。我有无限的期限(> 15),在分配内存和溢出旧代之间经过了很多时间。因此 - 内存泄漏。我想。
所以 - 问题 - 如何分析泄漏的内容?如你所见,我的伊甸园非常活跃。很多物体一直在被创造和销毁。
有没有办法只接受旧代的堆转储?或以某种方式识别完整堆转储中的旧gen(如果是,使用什么工具)?
编辑1: 澄清:我没有做 在内存中保留对象的任何事情。我在初次创业后分配的所有东西都应该年轻。
EDIT2: 新发现:我采取了堆转储,GCed像疯了一样,拿了另一个。第二个显示旧版使用率显着降低。两者之间的主要区别是终结者持有的对象。 不是终结者在年轻的GC循环中运行吗?他们总是等待清洁完整的GC吗?
答案 0 :(得分:1)
使用JVisualVM(自Java 6 Build 10之后的JDK的一部分或类似的东西),您可以查看内存中对象的TYPE。这将帮助您追踪泄漏的位置。当然,需要花费很多时间来挖掘代码,但这是我使用过的最好的工具,它始终可用且可靠。
注意传递的对象,可能是你有一个句柄被保存在一个未被清除的列表或数组中。我发现,如果我在几分钟内观察JVisualVM中正在创建和保存的对象数量,我通常会知道代码中的哪个位置可以挖掘未被释放的违规对象。
答案 1 :(得分:1)
在分配内存和溢出的内存之间传递了很多时间 老一代。因此 - 内存泄漏。我想
不是真的......只因为内存被添加到旧版本并不意味着它是内存泄漏。在年轻的收藏品中,通常的做法是将旧物品提升为旧品。正是在那些年轻的收藏中,旧的物体被添加到旧的时代。这可能只是你的应用程序仍在增加。在大型应用程序中,可能会有每天都没有使用的功能,这些功能可能会在您预期的时间内进入内存。
话虽这么说,如果你真的关心任何添加到旧版本的内存并想进一步调查,我建议在演示环境中运行这个应用程序。附上一个探查器(VisualVM将工作)并加载测试(JMeter是好的和免费的)您的应用程序。如果你查看对象,你可以了解对象的生成。您还希望看到当您的旧发电机达到完全GC启动的阈值时会发生什么(通常在70%-90%范围内)。如果您的旧发电机恢复到20%的阈值,那么就没有泄漏。在某些情况下,旧版本可能永远不会达到完整GC启动的程度,而是按照您的预期进行平衡。负载测试将有助于识别。
如果它没有恢复并且您确认存在内存泄漏,那么您将需要捕获堆转储(hprof)并使用MAT(Memory Analyzer Tool)之类的工具来分析转储以找到罪魁祸首。 / p>