Got a question about JVM GC, hoping somebody has seen this:
I have a clojure core.async event processing websocket service, currently processing in the 10s of thousands of events per second. It's accumulating memory in the old gen, and the other day crashed on an OOM.
However, if when the memory usage is high, I inspect the heap via jmap -hist:live
or generate a xprof heap dump via jmap -dump:live
, the old gen usage is cleaned up and the app continues along normally.
So, I'm confused, because if all it takes is an old gen GC, I don't understand why it ran out of memory entirely before.
Other details:
• The only GC or heap JVM args I specify are to increase the max heap size and pre-allocate it -Xmx6g -Xms6g
• jmap -heap
shows I'm using the default Parallel GC with 8 threads
Has anybody seen anything like this?
I realized that using the :live
option causes a major GC, which is useful for the running app to stay running, but not useful for understanding the growth, because the resultant dump doesn't contain any of the objects that were consuming the undesired memory in the first place.
So, I generated a dump without the :live
option and loaded it into YourKit. So far I've only learned that the largest driver of the retained size is categorized as "Objects unreachable from GC roots, but not yet collected."