我有一个java应用程序,在任何复杂执行之前处于空闲状态时,在Heap中使用23 MB,而TaskManager中的java.exe进程大小约为194 MB。经过一些复杂的操作后,java.exe的大小增长到大约500MB,堆大小也增长了。通过调用System.gc()方法,在几个完整的GC之后,堆大小减少到23MB。但java.exe的大小从大约600MB减少到大约237MB,其中仍有大约43 MB的数据。有没有办法减少这个?或者是由于某些行为?
答案 0 :(得分:12)
这很正常,不用担心。 JVM在需要执行某些复杂逻辑时获取内存。当java完成处理任务时,JVM仍将该内存保留为保留空间,并且不会释放回操作系统。此体系结构有助于提高性能,因为JMV不必再从底层操作系统请求相同的内存。它仍然在您在-Xmx JVM参数中定义的范围内。
有关一些有趣的详细信息,请参阅此IBM链接。 http://www-01.ibm.com/support/docview.wss?uid=swg21326774
不幸的是,这是JVM的一个灰色区域;你真的没有太多关于OS和JVM如何在彼此之间共享内存的控制。将JVM视为需要运行某些内存的虚拟操作系统。您的父操作系统和虚拟机都渴望获得资源,并且希望尽可能多地将所获得的资源挂在所获取的资源上。从操作系统请求更多内存是一项耗时的操作,因此大多数JVM 即使不再需要,也不会将内存释放回操作系统。
有关内部JVM内存管理的更多详细信息,请参阅Oracle的此白皮书。 http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf
我建议你先阅读IBM链接然后再深入研究白皮书中解释的奇怪的内存世界。这两个链接都非常丰富和有趣。
答案 1 :(得分:2)
java进程的OS足迹由
组成-Xmx
限制)一些垃圾收集算法将可用内存返回给操作系统,其他则没有。
在HotSpot JVM中,串行旧空间收集器(通常默认启用)将内存返回到OS(因此您可以看到进程收缩)。但是,-XX:+UseParallelOldGC
或-XX:+UseConcMarkSweepGC
等其他收集器永远不会将未使用的堆内存返回给操作系统。
HotSpot JVM具有管理/限制上述所有内存区域的选项,您可以在my blog中找到与内存大小调整和GC调整相关的JVM选项的完整列表。