JVM进程大小和内存堆大小之间有很大的差别。

5

我正在开发一款Java Swing应用程序,运行环境是Windows 8.1 64位,内存为4GB,JDK版本为8u20 64位。

问题是当我使用Netbeans profiler的Monitor选项启动应用程序时,出现了以下情况:

当第一个Jframe被加载时,应用程序的内存堆大约为18MB,JVM进程大小约为50MB(image1)。

然后,当我启动包含JFxPanel和webView的其他Jframe时,堆跳到了45MB,而JVM进程迅速跳到了700MB(image2),这非常令人困惑。 接着,当我关闭第二个JFrame并释放它时,会调用System.gc()进行GC(大多数情况下)。此时,堆会降至约20MB,但JVM进程的大小却不会下降(image3)。

为什么内存堆和JVM进程之间有如此巨大的差异(45 MB vs. 699 MB)? 为什么JVM需要那么多内存?如何减少它的使用量? 我使用以下VM选项启动应用程序:

-Xms10m  -Xmx60m -Xss192k
-XX:+UseG1GC -XX:MinHeapFreeRatio=5
-XX:MaxHeapFreeRatio=10  -XX:PermSize=20m
-XX:MaxPermSize=32m  

编辑:我刚才阅读了这个链接中的问题JVM memory usage out of control,他有同样的问题,但情况不同,他的堆大小约为总JVM进程内存大小的33%,而我的情况少于7%,他正在同时执行多个工作(Tomcat webapp),而我不是(Java Swing应用程序),他没有像我一样使用相同的VM参数启动应用程序。

更新: 第一个JFrame启动后(图片1)

First JFrame launched

第二个JFrame启动后(图片2)

Second JFrame launch

第二个JFrame关闭后(图片3)

Second JFrame closed

编辑2: 我刚刚尝试使用相同的VM参数运行相同的应用程序并添加了

-client 
-XX:+UseCompressedOops 

我使用了 JDK 8u25 32-bit,因为在这个答案中提到 https://dev59.com/Q3VC5IYBdhLWcg3wvT1a#15471505,64位版本没有包含JRE中的client文件夹并且会忽略-client参数。

结果是,当第二个JFrame打开时,进程的总内存跳到了540Mb,而堆大小(在三个点中)几乎与64位版本中的数字相同。这是否证实了这是一个与JVM有关的问题(相同的堆大小和总进程大小相差260Mb)?


尽管您可能没有完全相同的问题,但该问题的答案和评论仍适用于您的问题。如果不是这样,您需要提供更多详细信息,以便将此问题重新打开为非重复问题。 - Mark Rotteveel
他的问题的解决方案是停止同时运行作业并单独运行每个作业,这是与他的代码相关的问题,但我检查了我的代码,它只是一个包含两个Jframes的swing应用程序,似乎是与JVM相关的问题,除非我漏掉了什么。 - Waxren
被接受的答案清楚地解释了为什么内存使用量比堆大小大得多,例如许多线程或其他本机内容,Swing 可能也需要一些本机内容等等。 - Mark Rotteveel
感谢回复,你说得对,JVM进程的总内存使用量将超过堆大小,但正如本文https://plumbr.eu/blog/why-does-my-java-process-consume-more-memory-than-xmx中所述,总进程内存应为:最大内存= [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] = 60Mb + 32Mb + 20 * 192K = 95.75Mb,正如你在我的情况下注意到的,差距非常大。 - Waxren
我将会更新问题,并附上Netbeans Profiler的图片和更多细节。 - Waxren
显示剩余5条评论
1个回答

3
虚拟内存分配大多与实际内存使用无关(请参阅此答案),且与之相去甚远。JVM并非设计用于限制虚拟内存分配,请参见关于限制虚拟内存使用的问题。
最终用户可能在任务管理器中看到大量虚拟内存使用情况,但这大多是没有意义的。Windows任务管理器中显示的内存使用不同数字在本文中有解释。总体而言,在Windows任务管理器中查看“内存(私有工作集)”和“页面错误差”(后者的相关性在此答案中有解释)。

感谢您提供的出色答案。这解释了很多问题:“JVM并不旨在限制虚拟内存分配”。 - Waxren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接