How do you Force Garbage Collection from the Shell?

111,063

Solution 1

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 2

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

jcmd <pid> GC.run

Solution 3

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

Solution 4

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

for linux:

$ jcmd $(pgrep java) GC.run

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

Share:
111,063
eyberg
Author by

eyberg

Updated on August 03, 2021

Comments

  • eyberg
    eyberg almost 3 years

    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?

  • Dror Bereznitsky
    Dror Bereznitsky about 11 years
    This will trigger a heap dump not garbage collection
  • gtrak
    gtrak over 10 years
    force a garbage collection on all the javas: ps axf | grep java | grep -v grep | awk '{print "jmap -histo:live " $1}'|sh
  • Amin Abbaspour
    Amin Abbaspour over 10 years
    at least is solaris it does a force GC.
  • nafg
    nafg almost 10 years
    Where is that documented? What about without :live (e.g. when -F is needed)?
  • noahlz
    noahlz almost 10 years
    Why don't you people tell me about these things?! :)
  • noahlz
    noahlz almost 10 years
    Hello from the mysterious future of 2014. jcmd is now the right tool for the job.
  • Mircea Vutcovici
    Mircea Vutcovici almost 9 years
    Not even in Solaris, SIGQUIT will trigger neither a GC or a heap dump. SIGQUIT will trigger a thread dump only for HotSpot. For IBM JVM it is configurable.
  • Elad Tabak
    Elad Tabak over 7 years
    Will not trigger GC, just print the stack trace.
  • Thomas Rebele
    Thomas Rebele over 6 years
    if you get an "AttachNotSupportedException: Unable to open socket file", see my addition to this answer
  • dhockey
    dhockey about 6 years
    What about the following? Same thing? java.io.IOException: Operation not permitted
  • Thomas Rebele
    Thomas Rebele about 6 years
    I haven't encountered this error message yet. Maybe it works with sudo -u <process_owner> jcmd <pid> GC.run, could you try? The command should be safe
  • dhockey
    dhockey about 6 years
    I would have but I do not have sudo access on that machine.
  • Eyal Roth
    Eyal Roth almost 6 years
    And if you're getting Explicit GC is disabled, no GC has been performed that might be due to the -XX:+DisableExplicitGC VM argument. See: mail.openjdk.java.net/pipermail/serviceability-dev/2017-Augu‌​st/…
  • aled
    aled almost 6 years
    The tool works correctly. You just don't have the right permissions in the operating system to execute it. The same applies to other applications, even not using Java.
  • Cas
    Cas over 4 years
    This will only work when there's one java process running it seems. Otherwise it will interpret the second PID as the command for jcmd which is obviously not recognized and throw an error.
  • Ali Saleh
    Ali Saleh about 4 years
    This will work for Oracle JDK only, it will not work for open-jdk.
  • renedet
    renedet over 3 years
    Run jcmd before to discover all java <pid>
  • Geker
    Geker almost 3 years
    when run "jmap -histo:live <pid> ", the print result will contains the references before gc.
  • Admin
    Admin over 2 years
    @AliSaleh: It is also working with openjdk (in Debian and Ubuntu) for me. I installed it with sudo apt install openjdk-11-jdk-headless then ran with jcmd 0 GC.run (Process ID "0" means: "do it for all java processes") and all java processes had less RAM allocated (Resident Set Size RSS; see here stackoverflow.com/a/21049737/14972917 ). Virtual Memory Size (VSZ) is still the same as before (checked with ps -A u or ps -A u | grep java).