【发布时间】:2012-11-10 02:38:01
【问题描述】:
我有一个 java 程序,它不断调用java.util.zip 来压缩/解压缩数据。它会在几秒钟内耗尽内存。
我使用jmap 进行了内存转储,我正在使用jhat 查看它。
终结器摘要显示Total instances pending finalization: 0。如果我理解正确,我没有任何对象 (1) 具有 finalize() 方法,(2) 已被 GC 标记并且 (3) 正在等待最终确定。这看起来不错。
当我查看特定对象时,对该对象的唯一引用是java.lang.ref.Finalizer。 Finalizer 对象是为每个具有 finalize() 方法的对象创建的,无论该对象是否被 GC 处理。所以看起来没有什么能阻止这个 Deflater 对象被 GC 处理。
对象位于 0x7f4aeb7a35d0
java.util.zip.Deflater@0x7f4aeb7a35d0 的实例(51 字节)
对该对象的引用:
java.lang.ref.Finalizer@0x7f4aeb8607c8(64 字节):字段引用
程序在运行中被System.in.read() 暂停。一段时间后内存使用量不会下降。
更新:
我应该说清楚。内存转储显示许多对象没有经过 GC,但没有其他对象(终结器对象除外)引用它们。我正在尝试找出为什么它们没有被 GC 处理。
【问题讨论】:
-
@dashrb 我的代码中没有使用 Deflater。我正在使用使用 Deflater 的 Apache Thrift。 Deflater 不在范围内,因为
Show all members of the rootset仅显示 1 个对 Deflater 类的引用,但没有实例。 -
实际上,您的内存不足并且没有被 GC 标记的对象是不好的。这意味着您的代码(或您使用的某些库代码)保留了对对象的引用,因此 GC 无法收集它们。
-
@TedHopp 这就是我要找出的。我不知道如何找到这些引用,因为内存转储显示没有任何引用。
-
如果您使用 jmap 打印对象分配的直方图,这可能会显示哪种对象正在占用内存并为您提供下一步查看的线索。有一篇很好的文章 here 关于跟踪内存泄漏的工具。
-
为什么不使用内存配置文件来查看到底什么是活动的以及谁在引用谁?
标签: java memory-leaks garbage-collection jmap jhat