Could someone explain me (best would be to lead to documentation) what is the difference between the two:
jcmd ${jpid} GC.run_finalization
jcmd ${jpid} GC.run
As in the application (springboot + tomcat) after a test (using gatling) much memory stays allocated and not freed.
In the application life cycle:
- attack starts (gatling simulation), extra tomcat executor threads are started, attack ends
- after some time spring/tomcat session objects timeout (session.servlet.timeout)
- I would expect session objects to be released and extra tomcat executors to be released but it does NOT happen
- I waited a long time (let say days)... this is where the graph above starts
- If I execute GC.run_finalization - nothing happens (just faster "saw drop")
- If I execute GC.run - memory is released as shown on the image
The only documentation I found is https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc-- , but it confused me even more (I understood that GC.run_finalization would suggest finalization of objects for release while GC.run would suggest memory objects to be prepared for future reuse and not necessary freed).
Thanks in advance
There is documentation for
jcmdand its subcommands here:That documentation explains that
jcmd <pid or class> helpwill list the available commands, andjcmd <pid or class> help <command>will give you the help information for<command>.From what I can make out from a brief look at the JVM source code:
GC.runruns a full garbage collection. I don't know if finalizers are run (immediately), but I suspect not.GC.run_finalizationjust callsSystem.runFinalization(). According to the javadoc, this runs finalizers on objects that are pending finalization; i.e. Java objects that the GC has already found:finalize()method, andIt is not like that. A normal GC cycle is something like this:
finalizemethod is called and it is marked as having been finalized.The finalized object are left where they are. They will be deleted by the GC in a future collection provided that they are still unreachable.
Note that finalization is an old mechanism for tidying up objects before they are deleted. The vast majority of Java objects are never finalized.
So this is the explanation for the behavior that you are seeing.
GC_runtriggers a full collection which collects all spaces. That causes a lot more memory to be freed.GC_run_finalizationhas no effect because finalization doesn't free objects. And probably there are no finalizable objects on the queue anyway.