Search code examples
garbage-collectionjvmtomcat7

Schedule FullGC with DisableExplicitGC enabled


So the problem is that I would like to disable explicit GC to make sure no library can "force" FullGC with System.gc(). But I would like to still retain some control of when FullGC will happen. Is this doable? I mean is it possible to force (or strongly suggest) FullGC via JMX or some Tomcat management tools? Or maybe some command-line in cron?

The motivation of forcing FullGC is to make sure it doesn't happen in the middle of the day.

To my understanding FullGC will happen randomly with -XX:+DisableExplicitGC option. It will happen when Java will feel there is need to do this.

Or maybe there is some way to suggest Java something like "don't do FullGC from 7:00 to 16:00"?


Solution

  • Full GC can be forced even with -XX:+DisableExplicitGC by invoking a heap inspection operation like GC.class_histogram

    Via JMX

    MBean:     com.sun.management:type=DiagnosticCommand
    Operation: gcClassHistogram
    

    From the command line

    jcmd <pid> GC.class_histogram
    

    Patching System.gc

    Alternatively, you can intercept System.gc() calls by preloading a shared library with a custom JVM_GC implementation.

    Here is an example:

    #define _GNU_SOURCE
    #include <time.h>
    #include <dlfcn.h>
    
    void JVM_GC() {
        time_t timestamp = time(NULL);
        struct tm t;
        localtime_r(&timestamp, &t);
    
        // Don't do Full GC between 7:00 and 16:00
        if (t.tm_hour >= 7 && t.tm_hour < 16) {
            return;
        }
    
        void* original_jvm_gc = dlsym(RTLD_NEXT, "JVM_GC");
        if (original_jvm_gc != NULL) {
            ((void (*)()) original_jvm_gc)();
        }
    }
    

    Compile:

    gcc -O2 -fPIC -shared -o librestrictgc.so restrictgc.c -ldl
    

    Run:

    LD_PRELOAD=/path/to/librestrictgc.so java <args>