[
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]