我总是有一个关于堆内存行为的问题。
分析我的应用程序,我得到了上图。看起来一切正常。但我不明白的是,为什么在GC时,即使有足够的内存(红色圆圈),堆也会增长一点。
这意味着对于一个长时间运行的应用程序,它会在某个时间用完堆空间吗?

发布于 2010-10-15 23:03:20
不一定。垃圾收集器可以自由地以它认为合适的任何方式使用最大的已分配堆。根据当前行为(但具有不同的记忆条件)推断未来的GC行为并不能保证是准确的。
这确实有一个不幸的副作用,除非发生OutOfMemoryError,否则很难确定它是否会发生。一个合法的(但可能非常低效的)垃圾收集器可以简单地什么也不做,直到达到内存上限,然后对整个堆进行停止世界标记和清理。使用此实现,您将看到内存不断增加,并且可能会忍不住说OOME即将到来,但您就是说不出来。
对于如此小的堆大小,这里的增长可能只是由于记账/缓存大小对齐/等等。您正在谈论的是小于50KB的规模,所以我不应该担心。
如果您确实认为OutOfMemoryErrors存在合理的风险,那么证明这一点的唯一方法是将压力测试放在一起,并显示应用程序确实用完了堆空间。
发布于 2010-10-16 00:06:51
如果可用空间占总堆大小的比率低于某个阈值,则HotSpot垃圾收集器会在完整GC完成后立即决定增加总堆大小。可以使用垃圾收集器的许多-XX选项之一来调优此比率。
查看内存图,您将看到堆大小的增加发生在“锯点”;即局部最大值。其中每一个都对应于运行一个完整的GC。如果你真的仔细观察堆扩展的“点”,你会发现在每种情况下,紧跟在完整GC之后的空闲空间量都比前一个这样的“点”要高一点。
我认为现在发生的情况是应用程序的内存使用是周期性的。如果GC在周期的最高点或附近运行,它将无法释放与GC在低点或接近低点运行时一样多的内存。这种可变性可能足以导致GC扩展堆。
(另一种可能是您的应用程序存在缓慢的内存泄漏。)
对于长时间运行的应用程序来说,这意味着它会在某个时间用完堆空间吗?
不是的。假设你的应用程序的内存使用量(即可达对象占用的空间的整数)是周期性的,堆大小将接近一个固定的上限,并且永远不会超过它。当然,OOME不是不可避免的。
https://stackoverflow.com/questions/3943384
复制相似问题