1

I use Java Swing to create a simple GUI software. There exists a button on the panel that will trigger the generation of an ArrayList with a huge size. Each time I click this button the memory usage of my java program will increase significantly on my task manager, therefore I doubt that whether there exists the memory leakage problem.

After, I investigate my program by Jprofile and found (pictures below):

enter image description here enter image description here

As the pictures show, after the huge ArrayList is useless, the GC mechanism seems to work properly (really?). However, I want my program to reduce the committed size (instead of more free size) so that the total memory usage would be decreased when my program is idle.

I do not understand the Java memory usage, can anyone explain to me? How can I achieve my goal or the situation of my pictures is inevitable?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Simon Hu
  • 123
  • 1
  • 9
  • There's no simple answer to this other than "you can't force or guarantee the JVM to free committed memory". It depends on OS, JVM and garbage collector implementation. You may find this post helpful: https://stackoverflow.com/questions/30458195/does-gc-release-back-memory-to-os – Neil Coffey Aug 30 '20 at 11:22

1 Answers1

2

However, I want my program to reduce the committed size (instead of more free size) so that the total memory usage would be decreased when my program is idle.

The easy way to limit committed memory usage for a JVM is to to use -Xmx to set the maximum heap size. The problem is that if you limit the heap size too severely you are liable to trigger OutOfMemoryErrors.

Getting the JVM to give back memory is another matter. A JVM typically will give some memory back to the OS if it thinks that the heap has gotten too large. However, the default GC settings for this mean that the JVM / GC takes multiple GC cycles before it will give memory back. (A typical Java application's memory demand fluctuates, and it is inefficient for the GC keep resizing the heap larger and smaller again.)

This Q&A describes the process in more detail:

It is worth noting that the resize decision making (typically) happens after a Full GC. But a program that is idle won't be generating much garbage, and probably won't trigger the GC often, if at all. It might be necessary to manually run the GC by calling System.gc() to "encourage" it to give back memory. But there are downsides in doing that too:

Overall, my advice would be to set a reasonable value for -Xmx and stop worrying. If system performance gets too bad (e.g. due to Java using too much memory), buy more memory or a "new" machine that can take more memory. (2 minutes with Google found me a refurbished low-end desktop PC with 8GB RAM for AU$ 199.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • It's worth noting that the G1 (the default garbage collector) has improved in this aspect in JDK 12 and will return unused memory to OS promptly without having to wait for Full GC - the JEP is here: https://openjdk.java.net/jeps/346; it's also mentioned in the SO question you linked: https://stackoverflow.com/a/53284728/1184752 – Juraj Martinka Sep 01 '20 at 13:16
  • 1
    The JEP346 states: "In the default values of the configuration we disable this feature. " so no, it's not done by default – Wojtek Apr 02 '23 at 15:12