-
Notifications
You must be signed in to change notification settings - Fork 108
Classloader leak can lead to PermGen/Metaspace OutOfMemoryError #104
Description
I'm using logstash-gelf-1.11.0 configured via biz.paluch.logging.gelf.log4j.GelfLogAppender and deployed with war. As the application server is used Wildfly 10.1 but it must be reproduced in any server with worker pool.
After send log messages and redeploy application classes cannot be garbage collected due to ThreadLocal's that hold reference on custom class:
- GelfMessageAssembler.builders:ThreadLocal<PoolingGelfMessageBuilder>
- PoolingGelfMessage.STREAM_POOL:ThreadLocal<ReusableGzipOutputStream>
- OutputAccessor.accessors:ThreadLocal<ByteBufferOutputAccessor>
- OutputAccessor.streams:ThreadLocal<ByteBufferOutputStream>
Because of this PermGen/Metaspace OutOfMemoryError can be occurred
screen from Eclipse MAT:
I think the simplest solution is not to use ThreadLocal's for these cases and always create objects or implement ObjectPool.
I don't know which way is more appropriate, so I don't sent pull request.
If don't use ThreadLocal's then will be some performance degradation (actually such result is not representative due to big errors).
With ThreadLocal's
# Run complete. Total time: 00:01:04
Benchmark Mode Cnt Score Error Units
GelfMessageAssemblerPerf.createMessage avgt 5 97.158 ± 24.867 ns/op
GelfMessageAssemblerPerf.createMessageToJSON avgt 5 1716.895 ± 2933.147 ns/op
GelfMessageAssemblerPerf.createMessageToJSONPooledDirect avgt 5 507.275 ± 66.002 ns/op
GelfMessageAssemblerPerf.createMessageToJSONPooledHeap avgt 5 584.729 ± 90.140 ns/op
GelfMessageAssemblerPerf.createMessageToTCPBuffer avgt 5 1676.081 ± 2678.656 ns/op
GelfMessageAssemblerPerf.createMessageToTCPBufferPooledHeap avgt 5 589.000 ± 62.012 ns/op
GelfMessageAssemblerPerf.createMessageToTCPPooledDirect avgt 5 513.860 ± 42.689 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBuffer avgt 5 9812.872 ± 3898.791 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBufferPooledDirect avgt 5 7447.911 ± 502.219 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBufferPooledHeap avgt 5 7433.450 ± 331.027 ns/op
Without ThreadLocal's
# Run complete. Total time: 00:01:04
Benchmark Mode Cnt Score Error Units
GelfMessageAssemblerPerf.createMessage avgt 5 107.833 ± 39.569 ns/op
GelfMessageAssemblerPerf.createMessageToJSON avgt 5 1755.542 ± 3001.065 ns/op
GelfMessageAssemblerPerf.createMessageToJSONPooledDirect avgt 5 536.674 ± 147.928 ns/op
GelfMessageAssemblerPerf.createMessageToJSONPooledHeap avgt 5 581.223 ± 146.843 ns/op
GelfMessageAssemblerPerf.createMessageToTCPBuffer avgt 5 1632.048 ± 2789.088 ns/op
GelfMessageAssemblerPerf.createMessageToTCPBufferPooledHeap avgt 5 616.336 ± 137.137 ns/op
GelfMessageAssemblerPerf.createMessageToTCPPooledDirect avgt 5 538.507 ± 84.502 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBuffer avgt 5 9884.823 ± 4631.045 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBufferPooledDirect avgt 5 9906.995 ± 3867.064 ns/op
GelfMessageAssemblerPerf.createMessageToUDPBufferPooledHeap avgt 5 9888.346 ± 4327.754 ns/op