Java confusion about Runtime.memory() vs. Windows' Physical Memory Usage History graph

qraqatit :

I created for myself a Java rendering app for Windows (Win7 x64) that uses really a lot of memory during its rendering process (literally gigs in some huge projects...I have 8GB RAM in my PC and 6-core CPU) so I have to allocate like 4GB or even 8GB of RAM for it in my .bat file that starts my java application like this:

@ECHO OFF
java -Xmx8G -server -jar myapp %*
@if %errorlevel% neq 0 pause

When the rendering process ends it should unload all that is not needed anymore from the physical memory, and according to my in-app calculation ((r.totalMemory() - r.freeMemory()) / (1024.0 * 1024) + "MB") it really does that (I call System.gc() after the rendering thread ends: without this it is reporting no drop of memory usage - it is around 4GB, with this it report about 80MB of used memory).

My app usage of RAM is basically like this:

  • about 30MB without anything loaded yet, just the main app
  • about 80MB when I load some project (it does not matter how big, it would differ just in a few MB cos more GUI elements would be created than with some simple one)
  • up to 4GB when rendering is active
  • falls back to about 80MB when rendering ends

I even used memory profiling app from JAVA bin folder called Java VisualVM to be sure everything works as it should without any memory leaks...and according to its heap dump it really is working like that:

  • memory used with loaded project after the end of rendering is about 80MB
  • no open processes found
  • the largest files are like 3 files each of 25MB +/-

But I am really confused why when I look at the Windows graph of Memory Usage in Windows Task Manager there is almost absolutely no drop of the memoroy usage at all (maybe just a few MB's): it should drop like in hundreds of MB if not thousands (with said huge projects) - it unloads only after I close my app. And I really waited like 5 minutes, 10 minutes, 15 minutes...still no drop whatsoever in that graph window!

So I wonder: is there some specific switch I need to add to my .bat that would tell JVM "please, do unload all the unused memory my app used during render" or...?

qraqatit :

SO THIS IS THE FINAL SOLUTION FOR JDK v1.8.0_181 (my case)

It turns out that all I needed to ad to my .bat was -XX:+UseG1GC switch, so my java.bat code now finally looks like this and it is doing exactly what I expect it to: releasing unused memory back to system:

@ECHO OFF
java -XX:+UseG1GC -Xmx8G -server -jar myapp %*
@if %errorlevel% neq 0 pause

The "funny" part is I knew about this switch but as I read somewhere that it is used as default GC collector by default - that is: no need to set it manually - so I ignored that option completely - I just did not check the part where it said FROM THE SPECIFIC VERSION OF JDK :-). Well...

Big thank you goes to @apangin for solution suggestion!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=307072&siteId=1