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

Luke Butters edited comment on LOG4J2-1434 at 6/16/16 11:03 PM:
----------------------------------------------------------------

-Could you elaborate on why the issue is only one if it occurs under tomcat? If 
i don't use tomcat should I switch to a different logging framework?- No need 
Ralph points out I have created confusion by referencing tickets which only 
related to tomcat. To simplify replication I am not running a web server to 
demonstrate the issue.

I think we are talking about different issues. Perhaps the term memory leak is 
incorrect and a better wording would have been "StringBuffer in ThreadLocal 
causes excessive  memory usage after large log messages". I think in your case 
you actually had a leaking where in this case the ThreadLocal was created 
correctly however the object held by the thread local can only grow.
The example code demonstrates this. As the threads are kept around (e.g. from 
being re-used) the large StringBuffer is never cleaned up. So we can and end up 
in the case where 100 threads each have a StringBuffer which is large enough to 
hold 10M chars. This results in the log framework taking up a significant 
portion of memory.

I think it is worthwhile trying out the above code, if the logging framework 
has no issues then you will not run out of memory (I only gave my JVM 640M but 
we can increase the number of threads to make the problem occur) . Switching 
the log line to something like {{largeString.length()}} resulted in no memory 
issues, confirming the memory issue is in the log framework.

Having a look at your code base it seems you re-use getStringBuffer() which is 
good, however I suspect it will make fixing this issue even harder as the 
memory issue will be all over your application. Unless you know of a single 
spot where the size of the StringBuffer can be checked and the StringBuffer be 
shrunk or removed if it is too large.




was (Author: lukebutters7):
-Could you elaborate on why the issue is only one if it occurs under tomcat? If 
i don't use tomcat should I switch to a different logging framework?- No need 
Ralph points out I have created confusion by referencing tickets which only 
related to tomcat. To simplify replication I am not running a web server to 
demonstrate the issue.

I think we are talking about different issues. Perhaps the term memory leak is 
incorrect and a better wording would have been "StringBuffer in ThreadLocal 
causes excessive  memory usage after large log messages". I think in your case 
you actually had a leaking where in this case the ThreadLocal was created 
correctly however the object held by the thread local can only grow.
The example code demonstrates this. As the threads are kept around (e.g. from 
being re-used) the large StringBuffer is never cleaned up. So we can and end up 
in the case where 100 threads each have a StringBuffer which is large enough to 
hold 10M chars. This results in the log framework taking up a significant 
portion of memory.

I think it is worthwhile trying out the above code, if the logging framework 
has no issues then you will not run out of memory (I only gave my JVM 640M but 
we can increase the number of threads to make the problem occur) . Switching 
the log line to something like {{largeString.length()}} resulted in no memory 
issues, confirming the memory issue is in the log framework.

Having a look at your code base it seems you re-use getStringBuffer() which is 
good, however I suspect it will make fixing this issue even harder as the 
memory issue will be all over your application. Unless you know of a spot where 
the StringBuffer's internal array can be shrunk or the StringBuffer can be 
removed if it gets too large.



> StringBuffer in ThreadLocal can cause excessive memory usage after large log 
> messages
> -------------------------------------------------------------------------------------
>
>                 Key: LOG4J2-1434
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1434
>             Project: Log4j 2
>          Issue Type: Bug
>    Affects Versions: 2.6.1
>            Reporter: Luke Butters
>            Assignee: Remko Popma
>
> In an effort to speed up logging ThreadLocals have been introduced see 
> LOG4J2-1125 however this does causes memory issues.
> The problem of the ThreadLocal occurs when threads are re-used which is an 
> absolutely valid way of using java. For example an executor service can 
> re-use threads as well as Jetty.
> Below I demonstrate a contrived example of the memory leak:
> {code}
> int stringSize = 1024*1024*10; //~10MB maybe 20MB for UTF-16
>         StringBuilder sb = new StringBuilder(stringSize); 
>         for(int i = 0; i < stringSize; i++) {
>             sb.append('a' + i % 5);
>         }
>         
>         String largeString = sb.toString();
>         
>         sb = null; //Let it be GC'ed
>         ExecutorService es = Executors.newFixedThreadPool(100);
>         final CountDownLatch countDownLatch = new CountDownLatch(100);
>         for(int i = 0; i < 100; i++) {
>             es.execute(()-> {
>                 //Log the big string to demonstrate the issue.
>                 log.fatal(largeString);
>                 
>                 //Ensure we use all 100 of our threads by not releasing this 
> thread yet.
>                 countDownLatch.countDown();
>             }); 
>             
>             //We sleep for 2s so we more easily watch memory growth
>             Thread.sleep(2000);
>         }
> {code}
> I recommend that log4j2 immediately remove the ThreadLocal as a small gain in 
> performance does not outweigh the problems associated with memory leaks. 
> Finally other options for caching the StringBuilder with a ThreadLocal could 
> be considered for example we might re-use StringBuilders that are no larger 
> than 3k while removing the ones which are larger than 3k.



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

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to