减少 Java 堆大小

Posted

技术标签:

【中文标题】减少 Java 堆大小【英文标题】:Reducing Java heap size 【发布时间】:2014-12-22 08:29:49 【问题描述】:

我有一个应用程序使用大量内存来区分两个可能巨大的 (100k+) 目录的内容。对我来说,这样的操作会占用大量内存是有道理的,但是一旦我的 diff'ing 操作完成,堆的大小就会保持不变。

我基本上有代码实例化一个类来存储源和目标上每个文件的文件名、文件大小、路径和修改日期。我将添加、删除和更新保存在其他数组中。然后我 clear() 我的源和目标数组(现在可能每个 100k+),留下相对较小的添加、删除和更新数组。

在我clear() 我的目标和源数组之后,内存使用量(通过 VirtualVM 和 Windows 任务管理器可见)并没有下降。我对 VirtualVM(或任何分析器)的经验不足,无法弄清楚是什么占用了所有这些内存。 VirtualVM 的堆转储列出了保留大小为几兆字节的前几个对象。

有什么可以帮助我指明正确的方向吗?

【问题讨论】:

在查看内存使用情况时,您确定垃圾收集器已经运行了吗?只有在(可能是主要的)GC 运行后,内存使用才会下降。 根据 virtualvm,堆保持不变,而使用的堆将下降(到我期望的位置,不到总堆的一半)。堆大小与 Windows 任务管理器告诉我 java 使用的大致一致。我在分析应用程序时看到了通常的 GC 楼梯收集模式,我只是不知道为什么总堆仍然如此之大。 【参考方案1】:

如果在垃圾回收之后使用的堆发生故障,那么它可能会按预期工作。 Java 在需要更多内存时会增加其堆,但不会释放它——它更愿意保留它以防应用程序再次使用更多内存。请参阅Is there a way to lower Java heap when not in use? 了解为什么在使用的堆数量减少后堆没有减少的主题。

【讨论】:

我只是看了一眼那个帖子,它已经提供了很多信息。谢谢!【参考方案2】:

VM 根据命令行参数-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio 增大或缩小堆。当空闲百分比达到-XX:MaxHeapFreeRatio(默认为70)时,它将收缩堆。

Oracle's bug #6498735 对此进行了简短讨论。

【讨论】:

【参考方案3】:

根据您的代码,您可能会产生内存泄漏,而垃圾收集器无法释放它们。

我建议检测您的代码以发现潜在的内存泄漏。一旦排除或解决此问题,我将开始查看代码本身以寻求可能的改进。

请注意,例如,如果您使用 try/catch/finally 块。 finally 块可能根本不会被调用(或至少不会立即调用)。如果您在 finally 块中释放一些资源,这可能就是答案。

尽管如此,请阅读该主题,例如:http://www.toptal.com/java/hunting-memory-leaks-in-java

【讨论】:

以上是关于减少 Java 堆大小的主要内容,如果未能解决你的问题,请参考以下文章

JVM 的堆大小不断增加(但 usedMemory() 不断减少)

减少 JVM 中未使用的堆大小

了解java虚拟机—堆相关参数设置

在保留一些堆信息的同时减少托管程序的小型转储的大小?

Java JVM 参数设置大全

Java JVM 参数设置大全