In a running system, we see lots of "Full GC (System)" which indicates someone triggers System.gc().
Is there a way to find out where in the code this happens?
I did search all the available source but found nothing suspicious so it must be somewhere, probably another app that's running in the same container or the container itself.
You can change the Runtime class to log where gc() is being called to a file (System.gc() calls Runtime.gc())
To do this, edit a copy, compile it and add it to your -Xbootclasspath/p:
However a high number of Full GC is more likely to be due to insufficient survivor space or a full tenured space.
Can you try running
jstat -gccause {pid} 5s
Some library which you use might call explicit gc. You can disable it with -XX:-DisableExplicitGC
and take a look if it stops Full GC
in the logs
Use following brace script & jvisualvm with btrace plugin will reveal the caller of System.gc
easily.
// import all BTrace annotations
import com.sun.btrace.annotations.*;
// import statics from BTraceUtils class
import static com.sun.btrace.BTraceUtils.*;
// @BTrace annotation tells that this is a BTrace program
@BTrace
public class GCcaller {
// @OnMethod annotation tells where to probe.
// In this example, we are interested in entry
// into the Thread.start() method.
@OnMethod(
clazz="java.lang.System",
method="gc"
)
public static void func() {
// println is defined in BTraceUtils
// you can only call the static methods of BTraceUtils
println("about to start a System.gc!");
jstack();
}
}
In Java you cannot "call" the garbage collector. If you see the documentation when you call to the method System.gc(), the vm just takes as a suggestion to run the garbage collector, but there is no guarantee that is effectively called. Is an internal process that will be called automatically even if you don't call when it needs space in the stack.
If you are seeing a lot of Full GC, it may be a symptom of the application not releasing the resources correctly. You should monitor the heap to see what's the problem