Search code examples
javatomcatmemory-leaksthread-local

tomcat thread local memory leak


i'm using the thread locals approach to have a json serializer per each application thread to avoid the object creation each time i want to serialize it.

The code i'm using the following code:

public class JsonSerializerFactory {
    private static final ThreadLocal<JsonSerializer> JSON_SERIALIZER = 
        new ThreadLocal<JsonSerializer>() {
        @Override 
        protected JsonSerializer initialValue() {
             return new JsonSerializer();
        }
    };

public static JsonSerializer get() {
    return JSON_SERIALIZER;
}

}

each time i want to get the serializer i do:

JsonSerializerFactory.get()

When i'm shutting down the tomcat i see the following logs:

May 23, 2012 9:15:25 AM org.apache.catalina.loader.WebappClassLoader     clearReferencesThreads SEVERE: The web application [] appears to have started a thread named [Logback AsyncAppender Dispatcher [Async_Logger] - Thread-16] but has failed to stop it. This is very likely to create a memory leak.

I've read the Tomcat memory leak protection but i probably missing something there. Do I really have a leak, or should I ignore this message?

Could someone please explain?

see how to enhance tomcat thread pool behaviour


Solution

  • Every time you use a ThreadLocal you should really have some way to clear it up. What tomcat is complaining about is that the thread created internally by logback has referenced this thread local and there for it won't be collected (assuming that thread doesn't die).

    You can probably ignore this message if:

    • Hot application reloads are not that important, its only a leak if you reload the app
    • You know that the logback thread finishs when the application stops

    What you might want to think about is whether or not you need a ThreadLocal cache in the first place. Is that JsonSerializer really that expensive? are you certain it isn't thread safe.

    public class JsonSerializerFactory {
        public static JsonSerializer get() {
            // do this until you know you have a problem.
            return new JsonSerializer();
        }
    }