[Full GC (System) 25.575: [CMS: 20700K->22393K(655360K) <...>
System.gc()
. I think it would be superfluous to say that this is not used in our code.System.gc()
, with quite a good purpose. The fact is that during the launch process, the system pre-caches a huge amount of “static data” - information about users, currencies, etc., and this process generates quite a lot of garbage. Therefore, after we have finished all the preparations, and immediately before we report that the system has started, we call System.gc()
to at the same time get rid of unnecessary memory fragmentation. In addition, we do the same thing every night at 5:00 pm New York time, when the trading day ends, and our entire system goes offline for 5 minutes (maintenance mode), in order to remove the garbage accumulated during the day and defragment the memory . During working hours, we try to avoid the old-gen collection, since even ParNew assemblies that take 20-40 ms sometimes create unallowable delays. -Dsun.rmi.dgc.server.gcInterval=0x7FFFFFFFFFFFFFFE -Dsun.rmi.dgc.client.gcInterval=0x7FFFFFFFFFFFFFFE
0x7FFFFFFFFFFFFFFE
milliseconds (approximately once in 292471208 years).0x7FFFFFFFFFFFFFFE
, 0x7FFFFFFFFFFFFFFF
used. The boundary value causes an IllegalArgumentException
(code from the sun.misc.GC
class): if (this.latency == 9223372036854775807L) { throw new IllegalStateException("Request already cancelled"); }
Full GC (System)
! I had to strain my mind. To find out who is to blame for the System.gc()
call, I quickly wrote my implementation of the java.lang.Runtime
class, copying the standard class and changing its gc()
method (which is called when System.gc()
called). public native void gc();
public void gc() { Thread.dumpStack(); }
stdout
, since all that the Thread.dumpStack()
method Thread.dumpStack()
is create an exception and output it to the framework: /** * Prints a stack trace of the current thread to the standard error stream. * This method is used only for debugging. * * @see Throwable#printStackTrace() */ public static void dumpStack() { new Exception("Stack trace").printStackTrace(); }
java.lang.Runtime
class in our java machine with -Xbootclasspath/p:/tmp/runtime
, run ... And what do we see? java.lang.Exception: Stack trace at java.lang.Thread.dumpStack(Thread.java:1249) at java.lang.Runtime.gc(Runtime.java:689) at java.lang.System.gc(System.java:926) at sun.misc.GC$Daemon.run(GC.java:92)
sun.rmi.GC
class, and despite the fact that we set our -Dsun.rmi.dgc.*
Properties, they are still have no effect! For we use tomkat 6.0.35, and this bug was fixed in the next version, 6.0.36.JreMemoryLeakPreventionListener
, which is actually responsible for this behavior: /* * Several components end up calling: * sun.misc.GC.requestLatency(long) * * Those libraries / components known to trigger memory leaks * due to eventual calls to requestLatency(long) are: * - javax.management.remote.rmi.RMIConnectorServer.start() */ if (gcDaemonProtection) { try { Class<?> clazz = Class.forName("sun.misc.GC"); Method method = clazz.getDeclaredMethod("requestLatency", new Class[] {long.class}); method.invoke(null, Long.valueOf(3600000)); } catch (...) { ... } }
set />
gcDaemonProtection
flag simply disables this block of code responsible for the strange behavior. And - oh, a miracle! - That helped! Hourly garbage collection disappeared into oblivion, the support is happy, I went to drink tea.tomcat hourly full GC
, which gave me the desired link.Source: https://habr.com/ru/post/179309/
All Articles