简体   繁体   English

为什么这个java进程不释放内存?

[英]Why does this java process not release memory?

I have written a java application and I have run the java process under Fedora 24. Then I checked jconsole and found out that it uses around 5 to 10 megabytes of memory. 我编写了一个java应用程序,我在Fedora 24下运行了java进程。然后我检查了jconsole,发现它使用了大约5到10兆字节的内存。 The effect of garbage collection is also visible in the graph. 垃圾收集的效果在图中也可见。

Here is the screenshot: 这是截图: jconsole截图

Then I checked my System Monitor and found out that the same process ID has more than 100 megabytes memory usage. 然后我检查了我的系统监视器,发现相同的进程ID有超过100兆字节的内存使用量。

Here is the screenshot: 这是截图:

系统监视器截图

Please tell me why doesn't the process release unused memory? 请告诉我为什么这个过程没有释放未使用的内存?

Is there any way to release it? 有没有办法释放它?

There is a difference between used heap and allocated heap. 使用的堆和已分配的堆之间存在差异。 The blue line in your graph is the used heap - how much of the heap is actually holding objects. 图中的蓝线是用过的堆 - 实际持有对象的堆的数量。 What is not shown is the size of the heap which is allocated - this is larger, often much larger, so that the JVM can allocate more objects without running out of space and having to go back to the OS for more memory (which is expensive). 未显示的是分配的堆的大小 - 这个更大,通常要大得多,这样JVM可以分配更多的对象而不会耗尽空间并且必须返回操作系统以获得更多内存(这是昂贵的) )。 In your case, some of that 100mb which the system is showing is the JVM itself, but most of it is likely allocated but unused heap. 在您的情况下,系统显示的100mb中的一些是JVM本身,但其中大部分可能已分配但未使用的堆。

When you run a Java program without specifying the heap size you want it to use the JVM will try to figure out a sensible setting based on your machine, OS, JVM version etc. When I just ran a simple Hello World on my machine with 16GB of RAM and Java 8 it initially allocated 256mb for the heap. 当您运行Java程序而未指定您希望它使用的堆大小时,JVM将尝试根据您的计算机,操作系统,JVM版本等找出合理的设置。当我在16GB的机器上运行简单的Hello World时在RAM和Java 8中,它最初为堆分配了256mb。 Obviously much more than it needs! 显然远远超过它的需要! If I wanted to force it to use less I can use the -Xms command line to set the initial heap allocation and -Xmx to set the maximum allowed. 如果我想强制它使用less,我可以使用-Xms命令行设置初始堆分配,使用-Xmx设置允许的最大值。 My guess is that if you set something like -Xms20m you'd see less memory being used by your process. 我的猜测是,如果你设置像-Xms20m类的-Xms20m你会发现你的进程使用的内存更少。 In IntelliJ add that setting to the VM Options field in your run configuration. 在IntelliJ中,将该设置添加到运行配置中的VM Options字段。

The memory reported in the System Monitor is all memory used by the process, not just Java heap. 系统监视器中报告的内存是进程使用的所有内存,而不仅仅是Java堆。 This memory includes the: 这个记忆包括:

  • Executable files of the VM itself, and the libraries it has loaded VM本身的可执行文件及其加载的库
  • Working space for the VM as a process for use in such things as the Hotspot compiler, GC, IO buffers, screen and graphic buffers, reading VM files and the like 对于VM的工作空间在这样的事情作为热点编译器,GC,IO缓冲区,屏幕和图形缓冲的过程 ,阅读VM文件等
  • Java Heap and other reportable memory structures Java堆和其他可报告的内存结构

In your case, 10MB of the process is being used to store the Java stack and the Java objects. 在您的情况下,正在使用10MB的进程来存储Java堆栈和Java对象。 The other 90MB is the Java program itself and the memory internal to the VM. 另一个90MB是Java程序本身和VM内部的内存。

That's the short answer, but there is one other important consideration - Java can (and does) free excess heap back to the OS. 这是简短的答案,但还有另一个重要的考虑因素 - Java可以(并且确实)将多余的堆释放回操作系统。 This is controlled by the -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio flags. 这由-XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio标志控制。 By default the MaxHeapFreeRatio is 70% - which is almost exactly what is shown in your Heap graph (the saw tooth pattern from 6MB to a bit under 10MB). 默认情况下,MaxHeapFreeRatio是70% - 这几乎就是你的Heap图中显示的内容(锯齿图案从6MB到10MB以下)。 If your app had a significantly larger drop, you would see a (small) saw tooth pattern for the Java process in the System Monitor. 如果您的应用程序具有明显更大的下降,您将在系统监视器中看到Java进程的(小)锯齿模式。

For performance, you should generally allow the JVM to keep hold of a significant chunk of the heap freed from a GC. 为了提高性能,通常应该允许JVM保留从GC中释放的大量堆。 Why? 为什么? Because we know that the JVM will immediately need to start allocating memory again and it's more efficient for the process (and the OS) for Java to keep this. 因为我们知道JVM将立即需要再次开始分配内存,并且Java的进程(和操作系统)更有效地保持这一点。

So, in summary: 所以,总结一下:

  • The System Monitor shows the memory used by the whole JVM process 系统监视器显示整个JVM进程使用的内存
  • The Java heap is only one of the items using memory in the process Java堆只是进程中使用内存的项目之一
  • It is (generally) more performant for the JVM to hold (at least some of) the heap it frees after a GC because we're almost certainly going to use this within the next few seconds (通常)JVM保持(至少某些)它在GC之后释放的堆的性能(通常)更高,因为我们几乎肯定会在接下来的几秒钟内使用它
  • The Java heap in this case is oscillating within the normal bounds, and the default memory configuration in this case allows Java to hold all the excess heap after a GC 在这种情况下,Java堆在正常范围内振荡,在这种情况下,默认的内存配置允许Java在GC之后保存所有多余的堆

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM