我编写了一个java应用程序,我在Fedora 24下运行了java进程。然后我检查了jconsole,发现它使用了大约5到10兆字节的内存。 垃圾收集的效果在图表中也可见。
然后我检查了我的系统监视器,发现相同的进程ID有超过100兆字节的内存使用量。
以下是截图:
请告诉我为什么这个过程不会释放未使用的内存?
有没有办法释放它?
答案 0 :(得分:3)
使用堆和已分配堆之间存在差异。图中的蓝线是用过的堆 - 实际持有对象的堆的数量。未显示的是分配的堆的大小 - 这个更大,通常要大得多,这样JVM可以分配更多的对象而不会耗尽空间并且必须返回操作系统以获得更多内存(这是昂贵的) )。在您的情况下,系统显示的100mb中的一些是JVM本身,但其中大部分可能已分配但未使用的堆。
当你运行Java程序而没有指定你希望它使用的堆大小时,JVM将尝试根据你的机器,操作系统,JVM版本等找出合理的设置。当我在我的网站上运行一个简单的Hello World时具有16GB RAM和Java 8的机器最初为堆分配了256mb。显然远远超过它的需要!如果我想强制它使用更少,我可以使用-Xms
命令行设置初始堆分配,-Xmx
设置允许的最大值。我的猜测是,如果你设置-Xms20m
这样的东西,你会发现你的进程使用的内存更少。在IntelliJ中,将该设置添加到运行配置中的VM Options
字段。
答案 1 :(得分:2)
系统监视器中报告的内存是进程使用的所有内存,而不仅仅是Java堆。此内存包括:
在您的情况下,正在使用10MB的进程来存储Java堆栈和Java对象。另外90MB是Java程序本身和VM内部的内存。
这是简短的答案,但还有另一个重要的考虑因素 - Java可以(并确实)将多余的堆释放回操作系统。这由-XX:MinHeapFreeRatio
和-XX:MaxHeapFreeRatio
标志控制。默认情况下,MaxHeapFreeRatio是70% - 这几乎就是你的Heap图中显示的内容(锯齿图案从6MB到10MB以下)。如果您的应用程序具有明显更大的下降,您将在系统监视器中看到Java进程的(小)锯齿模式。
为了提高性能,通常应该允许JVM保留从GC中释放的大量堆。为什么?因为我们知道JVM将立即需要再次开始分配内存,并且Java的进程(和操作系统)更有效地保留它。
所以,总结一下: