2014-10-27 164 views
3

我有一个应用程序使用大量的内存区分两个潜在巨大(100k +)目录的内容。对我来说这样的操作会使用大量的内存是有意义的,但是一旦我的差异操作完成,堆仍然保持相同的大小。减少Java堆大小

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

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

任何帮助指向正确方向的东西?

+1

你确定垃圾收集器已经运行,当你看内存使用情况?内存使用率只会在GC(可能是主要的)运行后下降。 – cello 2014-10-27 08:03:47

+0

根据virtualvm,堆保持大致相同,而使用的堆将下降(大约我期望它,这是少于总堆的一半)。堆大小与Windows任务管理器告诉我java正在使用的内容大致相符。在分析应用程序时,我会看到通常的GC楼梯集合模式,我只是不知道为什么总堆仍然如此之大。 – tau 2014-10-27 08:14:21

回答

2

如果使用的堆在垃圾回收之后下降,比它有可能按预期工作。当Java需要更多内存时,Java会增加它的堆,但不会释放它 - 它更喜欢保持它以防应用程序再次使用更多内存。有关此主题的信息,请参阅Is there a way to lower Java heap when not in use?,了解为什么在使用的堆量减少后堆没有减少。

+0

我只是瞥了一眼那个线程,它已经非常翔实。谢谢! – tau 2014-10-27 08:27:27

1

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

我会建议您测试您的代码以便发现潜在的内存泄漏。一旦排除或修复,我会开始查看代码本身以寻求可能的改进。

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

然而读了关于这个问题的,比如这里:http://www.toptal.com/java/hunting-memory-leaks-in-java

2

虚拟机根据命令行参数-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio增大或缩小堆。当空闲百分比达到-XX:MaxHeapFreeRatio时,它将缩小堆积,其默认值为70.

Oracle's bug #6498735中有对此的简短讨论。