简体   繁体   中英

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. 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.

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). 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.

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. 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. My guess is that if you set something like -Xms20m you'd see less memory being used by your process. In IntelliJ add that setting to the VM Options field in your run configuration.

The memory reported in the System Monitor is all memory used by the process, not just Java heap. This memory includes the:

  • Executable files of the VM itself, and the libraries it has loaded
  • 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
  • Java Heap and other reportable memory structures

In your case, 10MB of the process is being used to store the Java stack and the Java objects. The other 90MB is the Java program itself and the memory internal to the VM.

That's the short answer, but there is one other important consideration - Java can (and does) free excess heap back to the OS. This is controlled by the -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio flags. 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). If your app had a significantly larger drop, you would see a (small) saw tooth pattern for the Java process in the System Monitor.

For performance, you should generally allow the JVM to keep hold of a significant chunk of the heap freed from a 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.

So, in summary:

  • The System Monitor shows the memory used by the whole JVM process
  • The Java heap is only one of the items using memory in the process
  • 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
  • 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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