与使用的%相比,意外的堆大小意外

时间:2011-03-25 09:27:59

标签: java linux jvm heap

有一个内存分配问题,我希望得到你的帮助。我们已经分析了一些顶级服务,我们注意到它们的RES值约为1.8GB,据我所知,这意味着他们当时正在保持1.8GB的内存。如果我们刚刚启动它们(它们基本上是从缓存中读取,进行处理,然后推送到另一个缓存),这样会好的,但是看到我们在CPU密集型处理完成后仍然看到这个,我们想知道它是否意味着某些东西没有像我们预期的那样被GC。

我们使用以下参数运行程序: -Xms256m -Xmx3096m 据我所知,这意味着初始堆大小为256,最大堆大小为3096.

现在我期待看到的是最初根据需要增长堆,然后在内存被释放时根据需要收缩(尽管这可能是我的第一个错误)。我们用jvisualvm实际看到的是:

  • 3分钟:用过的堆是1GB,堆 大小是2GB
  • 5分钟:我们已经完成了处理,所以 使用堆急剧下降到附近 足够的zilch,但只有堆大小 降至约1.5GB
  • 7分钟 - >:实时的小部分 定期处理,使用堆 只有100-200MB左右, 但是堆大小保持不变 约1.7GB。

我的问题是,为什么我的堆没有像我预期的那样缩小?这不是抢夺Linux盒子上有价值的内存的其他进程,如果是这样,我怎么能解决它?我们有时会看到内存错误,并且这些进程被分配了最“意外”的内存大小,我认为最好从它们开始。

干杯, 戴夫。

(请原谅我们对JVM内存调整缺乏了解!)

4 个答案:

答案 0 :(得分:3)

您可能希望看到有关调整堆扩展和收缩的this answer。默认情况下,JVM不会过于积极地缩小堆。此外,如果堆有足够的可用空间很长一段时间,它将不会触发GC,我认为这是唯一一次考虑缩小它。

理想情况下,您将最大值配置为一个值,使您的应用程序在满负载下具有足够的空间,但如果始终全部使用,则可以接受操作系统性能。为可预测性和可能更好的性能设置最小值到最大值并不罕见(我没有任何可以参考的内容)。

答案 1 :(得分:1)

我没有完整的答案,但是a similar question has come up before。从前面的讨论中,您应该调查-XX:MaxHeapFreeRatio=作为调整参数,以强制堆释放回操作系统。有documentation here,我相信默认值允许JVM保留大量未使用的堆。

答案 2 :(得分:0)

嗯,GC并不总是在你想到的时候运行,并且它并不总是收集可以忽略的东西。如果它几乎耗尽堆空间,它也可能只从旧的gen空间开始收集对象(因为从旧的收集通常会涉及GC试图避免的世界停止集合,直到它确实需要做它)。

答案 3 :(得分:0)

也许您可以尝试使用TPTP,visualvm或JProbe(商业,但可以试用)进行一些分析,以确切了解会发生什么。

要注意的另一件事是文件处理程序;我没有详细信息,但我的一位同事在几年前遇到了由打开许多文件的进程引起的堆饱和问题,并发现每次打开一个4kb缓冲区都在本机堆中分配,在处理结束时释放。我希望这些含糊不清的迹象可能会有所帮助......