[ 
https://issues.apache.org/jira/browse/LOG4J2-1116?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15186536#comment-15186536
 ] 

Remko Popma commented on LOG4J2-1116:
-------------------------------------

ThreadLocals containing JDK classes (StringBuilder, etc) are not a problem. 
Their classloader is the system classloader, not the web app classloader, so 
these ThreadLocals do not have a reference to the web app classes and do not 
prevent web app classes from being garbage collected.

This idiom is safe:

{code}
class SafeClass {
    // The type of this field is java.lang.ThreadLocal, and
    // both the key (ThreadLocal) and the value (StringBuilder) are JDK classes.
    // This idiom is safe and will not cause memory leaks in web apps.
    static ThreadLocal<StringBuilder> safe = new ThreadLocal<StringBuilder>();

    private StringBuilder getThreadLocalStringBuilder() {
        StringBuilder value = safe.get();
        if (value == null) {
            value = new StringBuilder(1024);
            safe.set(value);
        }
        return value;
    }
}
{code}
However, as soon as we create an anonymous subclass like below we cause memory 
leaks again:

{code}
class MemoryLeakingClass {
    // The type of this field is MemoryLeakingClass$1, an anonymous subclass of 
java.lang.ThreadLocal!
    // In a web app, the classloader of this class is the web app class loader: 
may cause memory leak...
    static ThreadLocal<StringBuilder> anonymousSubclass = new 
ThreadLocal<StringBuilder>() {
        @Override
        protected StringBuilder initialValue() {
            return new StringBuilder(1024);
        }
    };
}
{code}

I have thought about ways to clean up the ThreadLocals on Log4j shutdown but I 
haven't found a way yet.
The problem is that you can only remove() the ThreadLocal value for _the 
current_ thread. So for each thread that has a ThreadLocal value pointing to a 
web app-loaded class, you would want that thread to call ThreadLocal.remove(). 
The only way I can see we can prevent memory leaks in a web container is if we 
can get a reference to the web container's thread pool, and schedule a Runnable 
on each thread in the pool, and that Runnable would call ThreadLocal.remove(). 
I don't see yet how we can do that...

> upgrade to log4j2 causes too frequent minor gc
> ----------------------------------------------
>
>                 Key: LOG4J2-1116
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1116
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.3
>         Environment: jdk1.6 
> slf4j 1.7.9
> log4j2.3
>            Reporter: Mingjiang Shi
>            Priority: Critical
>
> We used slf4j+log1.2 in our spring web application. Due to the log4j1.0 
> performance issue, we upgrade it to log4j2. When it goes to production, it 
> experienced very frequent minor gc (once per second) even though the eden 
> area is not full. For example, the eden area just occupied 10%, the minor gc 
> also happens. The issue disappears when rolling back to log4j1.2. 
> Can anyone show some hints on diagnose this issue? Thanks!



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to