How do you Force Garbage Collection from the Shell?

JavaGarbage CollectionJmxJmap

Java Problem Overview


So I am looking at a heap with jmap on a remote box and I want to force garbage collection on it. How do you do this without popping into jvisualvm or jconsole and friends?

I know you shouldn't be in the practice of forcing garbage collection -- you should just figure out why the heap is big/growing.

I also realize the System.GC() doesn't actually force garbage collection -- it just tells the GC that you'd like it to occur.

Having said that is there a way to do this easily? Some command line app I'm missing?

Java Solutions


Solution 1 - Java

Since JDK 7 you can use the JDK command tool 'jcmd' such as:

jcmd <pid> GC.run

Solution 2 - Java

If you run jmap -histo:live <pid>, that will force a full GC on the heap before it prints anything out.

Solution 3 - Java

You can do this via the free jmxterm program.

Fire it up like so:

java -jar jmxterm-1.0-alpha-4-uber.jar

From there, you can connect to a host and trigger GC:

$>open host:jmxport
#Connection to host:jmxport is opened
$>bean java.lang:type=Memory
#bean is set to java.lang:type=Memory
$>run gc
#calling operation gc of mbean java.lang:type=Memory
#operation returns: 
null
$>quit
#bye

Look at the docs on the jmxterm web site for information about embedding this in bash/perl/ruby/other scripts. I've used popen2 in Python or open3 in Perl to do this.

UPDATE: here's a one-liner using jmxterm:

echo run -b java.lang:type=Memory gc | java -jar jmxterm-1.0-alpha-4-uber.jar -n -l host:port

Solution 4 - Java

Addition to user3198490's answer. Running this command might give you the following error message:

$ jcmd 1805 GC.run    
[16:08:01]
1805:
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
...

This can be solved with help of this stackoverflow answer

sudo -u <process_owner> jcmd <pid> GC.run

where <process_owner> is the user that runs the process with PID <pid>. You can get both from top or htop

Solution 5 - Java

for linux:

$ jcmd $(pgrep java) GC.run

jcmd is packaged with the JDK, $(pgrep java) gets the process ID of java

Solution 6 - Java

There's a few other solutions (lots of good ones here already):

The following example is for the cmdline-jmxclient:

$ java -jar cmdline-jmxclient-0.10.3.jar - localhost:3812 'java.lang:type=Memory' gc

This is nice because it's only one line and you can put it in a script really easily.

Solution 7 - Java

I don't think there is any command line option for same.

You will need to use jvisualvm/jconsole for same.

I would rather suggest you to use these tools to identity , why your program is high on memory.

Anyways you shouldn't force GC, as it would certainly disturb GC algorithm and make your program slow.

Solution 8 - Java

If you are using jolokia with your application, you can trigger a garbage collection with this command:

curl http://localhost:8558/jolokia/exec/java.lang:type=Memory/gc

Solution 9 - Java

Consider using GNU parallel with jcmd as below for multiple processes;

parallel 'jcmd {} GC.run' ::: $(pgrep java)

Solution 10 - Java

In addition to user3198490's answer, if nothing really changes after you run jcmd <pid> GC.run, the reason could be:

GC.run essentially calls java.lang.System.gc(), which is just a hint to gc and the JVM is free to ignore it.

If you want to ensure a full GC is FORCED, a choice is to use:

jcmd <pid> GC.heap_dump filename.hprof

The original purpose of this command is to create a heap dump file named filename.hprof. But as a side effect, in order to reach all the live objects, it "request a full GC unless the -all option is specified".

There are some other commands like jmap -histo:live <PID> mentioned in this answer triggers GC as a side effect in the same way.

Solution 11 - Java

In addition:

  • To run GC for multi process with the same application, jar file, etc. Use:
jcmd your_application.jar GC.run
  • To run GC on windows, try:
cd C:\"Program Files"\Java\jdk-13.0.2\bin
.\jcmd.exe your_application.jar GC.run
  • MacOS / Linux:
jcmd your_application.jar GC.run
# or
/usr/bin/jcmd your_application.jar GC.run

Solution 12 - Java

just:

kill -SIGQUIT <PID>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneybergView Question on Stackoverflow
Solution 1 - Javauser3198490View Answer on Stackoverflow
Solution 2 - JavaWill HartungView Answer on Stackoverflow
Solution 3 - JavaHarold LView Answer on Stackoverflow
Solution 4 - JavaThomas RebeleView Answer on Stackoverflow
Solution 5 - JavaXuejun LiuView Answer on Stackoverflow
Solution 6 - JavaThe AlchemistView Answer on Stackoverflow
Solution 7 - JavaYoKView Answer on Stackoverflow
Solution 8 - JavadustmachineView Answer on Stackoverflow
Solution 9 - JavaSan Emmanuel JamesView Answer on Stackoverflow
Solution 10 - JavaxdcsyView Answer on Stackoverflow
Solution 11 - JavaNavy FlameView Answer on Stackoverflow
Solution 12 - JavaAmin AbbaspourView Answer on Stackoverflow