Java堆溢出,强制垃圾收集

时间:2010-03-12 00:12:29

标签: java heap

我创建了一个带有一系列子项的trie树。删除单词时,我将子项设置为null,我假设删除该节点(delete是相对术语)。我知道null不会删除子节点,只需将其设置为null,这在使用大量单词时会导致溢出堆。

在linux上运行top,我可以很快看到我的内存使用量达到1gb,但是如果我在删除后强制进行垃圾收集(Runtime.gc()),则内存使用率将达到50mb并且永远不会高于此值。据我所知,java默认情况下会在堆溢出发生之前运行垃圾收集,但是我无法看到这种情况发生。

5 个答案:

答案 0 :(得分:5)

(这个评论太长了)

与流行的看法相反,你 CAN 真的强迫用Java加入GC,但使用 System.gc()完成。真正强制GC的方法是使用JVMTI的 ForceGarbageCollection()调用。不要问我更多,我在这里问了一个问题,没有人发现它很有趣(没有upvotes),也没有人能回答它,但JVMTI的 ForceGarbageCollection()是很多Java程序如IntelliJ,NetBeans的,VisualVM,Eclipse等。确实强制GC

Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

现在......您可能想要这样做,您可能想要使用“无保证”系统提示GC。 gc()电话。

你有多少话开始有问题?当您需要使用疯狂的单词数时,有非常紧凑的数据结构。您确定使用的是正确的数据结构吗?您确定没有泄漏吗?

答案 1 :(得分:3)

您是指未释放到操作系统的内存 - 即top和类似程序显示Java进程需要1GB内存吗?即使Java的垃圾收集器从其堆中释放内存,它仍然可以保留内存,以便将来的分配不需要从操作系统请求更多内存。

要查看Java对象实际使用了多少堆空间,请使用VisualVM或类似的Java特定工具。如果您的计算机有大量内存,那么JVM将使用它(IIRC,特别是服务器VM被调整为保留更多内存),但您始终可以使用-Xmx和其他JVM选项来限制它。

答案 2 :(得分:1)

好的,你得到java.lang.OutOfMemoryError: Java heap space 最有可能的是,Runtime.gc()无济于事,因为如果可以的话,JVM已经做了一个gc。

这可能是内存泄漏。如果我是你,我会仔细检查我的代码,看看是否某些引用仍然存在。

  

所以孙子们不会被删除?   当我删除时,我只是设置它   子节点为null,但不是   孩子的孩子,但那些   孩子们没有被初始化,   只创建(Node [] children = new   节点[26]

如果你做children=null,是的,整个数组应该是gc'd。前提是你没有提到某些东西。

但谁知道罪魁祸首是什么。它甚至可能不是这些“儿童”节点。您可能希望使用visualVm并找出正在累积的对象。您可以使用更复杂的工具,如JProfiler,并检查引用等,但如果您只是构建一个trie,我想更简单的方法是遍历您的代码并发现泄漏。

答案 3 :(得分:0)

分配给进程(即JVM)的内存不一定返回给Unix中的操作系统。因此,即使Java虚拟机可能已经完全垃圾收集了堆,但是进程大小可能保持不变。

通常情况下,这可能不会产生太大影响,因为未使用的堆将被分页并且不再被重新分页。查看ps -u输出中虚拟大小(VSZ)和驻留集大小(RSS)之间的差异,区别在于换出的页数。

答案 4 :(得分:0)

只有在任何可访问对象的链接无法访问对象后,才会删除该对象。您是否仍然可以参考相关对象?

顺便说一下,Runtime.gc()有时只是提示应该运行垃圾收集。