How do you Force Garbage Collection from the Shell?
Asked Answered
S

12

136

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?

Sarene answered 19/8, 2010 at 16:17 Comment(1)
Not the same as #1481678Culex
B
26

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
Brunei answered 19/8, 2010 at 16:33 Comment(0)
M
403

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

jcmd <pid> GC.run

Malamute answered 15/1, 2014 at 14:10 Comment(7)
Why don't you people tell me about these things?! :)Pimentel
if you get an "AttachNotSupportedException: Unable to open socket file", see my addition to this answerPlait
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-August/…Quezada
This will work for Oracle JDK only, it will not work for open-jdk.Lafave
Run jcmd before to discover all java <pid>Godspeed
@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 https://mcmap.net/q/25489/-what-is-rss-and-vsz-in-linux-memory-management ). Virtual Memory Size (VSZ) is still the same as before (checked with ps -A u or ps -A u | grep java).Dentilabial
is it safe to invoke this command on prod server ?Textualism
K
110

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

Kalmick answered 19/8, 2010 at 16:39 Comment(4)
force a garbage collection on all the javas: ps axf | grep java | grep -v grep | awk '{print "jmap -histo:live " $1}'|shUnderclassman
Where is that documented? What about without :live (e.g. when -F is needed)?Evslin
Hello from the mysterious future of 2014. jcmd is now the right tool for the job.Pimentel
when run "jmap -histo:live <pid> ", the print result will contains the references before gc.Elmira
B
26

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
Brunei answered 19/8, 2010 at 16:33 Comment(0)
P
21

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

Plait answered 6/2, 2018 at 15:22 Comment(4)
What about the following? Same thing? java.io.IOException: Operation not permittedReliquiae
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 safePlait
I would have but I do not have sudo access on that machine.Reliquiae
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.Blatherskite
S
12

for linux:

$ jcmd $(pgrep java) GC.run

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

Silvereye answered 25/9, 2019 at 20:6 Comment(1)
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.Gourley
D
7

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.

Desirous answered 19/8, 2010 at 16:37 Comment(0)
C
1

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.

Concordance answered 14/7, 2021 at 7:19 Comment(0)
P
0

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.

Passenger answered 19/8, 2010 at 16:30 Comment(1)
I'm sure there was a way to do it in 2010, but even if it wasn't, at 2022 this is an incorrect answer. One of the ways to do it is using jcmdKreegar
D
0

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
Decarbonate answered 22/12, 2017 at 19:21 Comment(0)
P
0

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

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

Parabola answered 6/4, 2021 at 4:0 Comment(0)
S
0

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
Systemic answered 3/8, 2021 at 0:54 Comment(0)
P
-17

just:

kill -SIGQUIT <PID>
Pass answered 17/1, 2013 at 3:5 Comment(4)
This will trigger a heap dump not garbage collectionEngdahl
at least is solaris it does a force GC.Pass
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.Ingroup
Will not trigger GC, just print the stack trace.Jugal

© 2022 - 2024 — McMap. All rights reserved.