事实收集:
log4j 2.6提供了无垃圾日志记录,它无需每次都创建新的字符串,而是重用保存在threadlocal中的stringbuilder。
默认情况下,在webApp中禁用log4j的无垃圾模式,因为webApp会重用线程,并且在线程中保存日志可能会导致几天内建立stringBuilder。
我正在WebApp中使用log4j,并验证ENABLE_THREADLOCALS
字段为false。
当我以以下方式登录时:
log.info("log statement with parameter {}", someString);
log.info(""log statement with concatenation " + someString");
我知道,即使在完整的GC之后,第一条语句仍保留在堆内存中。 第二条语句不适用。
我遍历了log.info的代码,发现第一个使用“ ParameterizedMessage
”,而第二个使用“ SimpleMessage
”。
ParametrizedMessage
的创建是使用ThreadLocal
s进行的,即使对于WebApp也是这样,它具有注释:
"// storing JDK classes in ThreadLocals does not cause memory leaks in web apps, so this is okay"
我的问题是,以上评论是否正确,因为在WebApp中使用{}登录时遇到内存泄漏问题。
PS:重新启动webApp时没有问题。重新启动后,所有内容都会清除。但是,当webApp连续运行几天,并且threadLocals大小不断增加时,这是一个问题。
答案 0 :(得分:0)
似乎您遇到了一个错误:https://issues.apache.org/jira/browse/LOG4J2-1417
org.apache.logging.log4j.util.Unbox类存储一个非JDK类 (Unbox $ State)在静态ThreadLocal字段中。
这可能会导致共享线程池的容器中的内存泄漏 在应用程序之间。
尝试使用2.6.2或更高版本。