I have a Java application that normally has very healthy garbage collection statistics. A tenured collection normally happens every hour or so and the STW portions take just fractions of a second. But strangely a collection always happens within about the first five minutes of app startup. This is a real problem because at that time, CPU usage is already much higher than normal (due to increased network calls that eventually get cached), so these pauses are always longer than normal and even run past 8 seconds if I'm doing a restart under extremely heavy load.
Here are the JVM args:
-Xms4096m
-Xmx4096m
-XX:PermSize=768m
-XX:MaxPermSize=768m
-XX:SurvivorRatio=6
-XX:NewSize=1024m
-verbose:gc
-XX:-DisableExplicitGC
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution
-XX:+HeapDumpOnOutOfMemoryError
-XX:MaxDirectMemorySize=2048m
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-XX:+PrintConcurrentLocks
-XX:+ExplicitGCInvokesConcurrent
The question here is what triggers this tenured collection since there is almost 2gb free in old gen when it occurs. Here's the usage under normal circumstances right before a tenured collection:
concurrent mark-sweep generation total 3145728K, used 2897098K
And here's the usage just before a tenured collection is triggered within the first few minutes of startup:
concurrent mark-sweep generation total 3145728K, used 1573655K
My understanding is that a tenured collection should only occur when old gen is nearly full; what could trigger it otherwise?