为什么log4j gc free logging不适合webapp

时间:2017-08-16 18:36:47

标签: java web-applications garbage-collection log4j2

我目前正在迁移我们的Web服务和Web应用程序以使用Log4j2.6日志记录。根据网站上提供的信息,Web应用程序支持部分无垃圾日志记录,并且由于内存泄漏的可能性,不支持完全无垃圾日志记录。如果我们在第一种情况下设置了TreadLocal而在第二种情况下设置了ThreadLocal,那么任何人都可以帮助我理解日志记录是如何工作的。

此外,我想知道在什么情况下部分无垃圾日志记录比完全无垃圾日志记录更好。

1 个答案:

答案 0 :(得分:2)

在无垃圾模式下,Log4j2重用LogEvent对象。为了防止多个线程同时修改同一个LogEvent,每个线程都有自己的LogEvent。这是通过ThreadLocal实现的。

ThreadLocals的一个关键点是放在它们中的任何内容都会保留在那里,直到它被明确删除或线程死掉。即使没有对我们的LogEvent的其他引用,它也不会被垃圾收集,因为ThreadLocal仍然有对它的引用,而线程是GC根。

Web应用程序容器通常在自定义类加载器中加载Web应用程序。这允许停止和重新加载Web应用程序的不同版本,而无需重新启动Web应用程序容器。但是,如果某些内容仍然引用了以前版本的Web应用程序的类,那么该类以及所有相关类(包括自定义类加载器)都无法进行垃圾回收。

什么时候会发生这种情况?当Web应用程序容器具有在Web应用程序之间共享的线程池时,并且在重新加载Web应用程序时不刷新。然后,池中的线程仍然具有对LogEvent对象和Web应用程序以前版本的类的ThreadLocal引用,因此无法对此类进行垃圾回收,并且您有内存泄漏。

<强>结论 如果满足以下两个条件,则可以在Web应用程序中使用无垃圾日志记录:

  1. 不在Web应用程序之间共享线程池
  2. 重新加载Web应用程序时,其线程池也会关闭并重新启动
  3. 如果以上都是真的,我相信您可以配置Log4j2以使用无垃圾日志记录而不会有内存泄漏的风险。当然,您需要进行尽职调查和测试。