简体   繁体   English

Log4j2 AsyncAppender 线程在 tomcat 取消部署时不会死,导致内存泄漏

[英]Log4j2 AsyncAppender thread does not die on tomcat undeploy causing memory leak

The stack I am using at the moment is:我目前使用的堆栈是:

  • log4j2 rc1 log4j2 rc1
  • spring 3.2 core and web spring 3.2 核心和网络
  • tomcat 7.0.47 Tomcat 7.0.47
  • java 1.6.0_45 java 1.6.0_45
  • Windows 7 Windows 7的

I don't have the ability to alter the tomcat version or java version and I would prefer not to alter the log4j version and spring version.我没有能力更改 tomcat 版本或 java 版本,我不想更改 log4j 版本和 spring 版本。

Essentially, when I undeploy my webapp I receieve a SEVERE warning saying:本质上,当我取消部署我的 webapp 时,我收到一个严重的警告说:

SEVERE: The web application [/MyApp] appears to have started a thread named
[AsyncAppender-AsyncFile] but has failed to stop it. This is very likely to 
create a memory leak

I can confirm that it does create a memory leak and this is what I am trying to fix.我可以确认它确实造成了内存泄漏,这就是我要解决的问题。

So far I have attempted to create a custom ServletContextListener which contains the following code:到目前为止,我已经尝试创建一个包含以下代码的自定义 ServletContextListener:

@Override
public void contextDestroyed(ServletContextEvent event) {
    System.out.println("Shutting down logger");
    try {
        ((Log4jWebSupport) event.getServletContext().getAttribute(
            Log4jWebSupport.SUPPORT_ATTRIBUTE)).clearLoggerContext();
        ((LifeCycle) LogManager.getContext()).stop();
    } catch (Exception e) {

    }
}

None of these two lines seems to fix the problem, however I can confirm that this code is being executed due to my sysout statement appearing in the tomcat console.这两行似乎都没有解决问题,但是我可以确认由于我的 sysout 语句出现在 tomcat 控制台中,此代码正在执行。

I am using log4j2 through an interceptor which I am setting up using Spring我正在通过我使用 Spring 设置的拦截器使用 log4j2

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <ref bean="LoggingInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
<bean id="LoggingInterceptor" class="MyLoggerClass">

The interceptor works correctly and the logs appear where I expect them to.拦截器工作正常,日志出现在我期望的地方。 My implementation of the logger is:我对记录器的实现是:

private static Logger log = LogManager.getLogger("MetricLogger");

public void log(LogPayload payload) {
    if(payload != null){
        log.info(payload.get());
    }
}

Where LogPayload.get() returns a String.其中LogPayload.get()返回一个字符串。

As I am using the logging facility across multiple webapps I have created a separate jar file containing this and the classes recording the measurements.当我在多个 web 应用程序中使用日志记录工具时,我创建了一个单独的 jar 文件,其中包含这个文件和记录测量值的类。 I have included this using maven and I compile it into the final war file I deploy to tomcat.我已经使用 maven 将其包含在内,并将其编译到部署到 tomcat 的最终 war 文件中。 This war file is included on a per app basis and is not included in the global tomcat/lib folder.此 war 文件包含在每个应用程序的基础上,不包含在全局 tomcat/lib 文件夹中。

Does anyone have any insight as to why I get my memory leak issue and what the possible solutions are to fixing this?有没有人知道为什么我会遇到内存泄漏问题以及解决这个问题的可能解决方案是什么?

Many thanks for your help and please let me know if you need further information.非常感谢您的帮助,如果您需要更多信息,请告诉我。

The solution to this that I have so far found is that I need to include the following snippet in the web.xml.到目前为止,我找到的解决方案是我需要在 web.xml 中包含以下代码段。

<listener>
    <listener-class>org.apache.logging.log4j.core.web.Log4jServletContextListener</listener-class>
</listener>

<filter>
    <filter-name>log4jServletFilter</filter-name>
    <filter-class>org.apache.logging.log4j.core.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>log4jServletFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

This is specific to servlet spec 2.5.这是特定于 servlet 规范 2.5 的。 This seems to resolve the memory leak issue.这似乎解决了内存泄漏问题。

Adding the below snippet worked for me to get rid of memory leak due to Async-Appender threads not getting shut down even after the application shutdown.添加以下代码段对我有用,可以消除由于 Async-Appender 线程即使在应用程序关闭后也不会关闭而导致的内存泄漏。 Thank you @kipper_t.谢谢@kipper_t。

<listener>
    <listener-class>org.apache.logging.log4j.core.web.Log4jServletContextListener</listener-class>
</listener>

<filter>
    <filter-name>log4jServletFilter</filter-name>
    <filter-class>org.apache.logging.log4j.core.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>log4jServletFilter</filter-name>
    <url-pattern>/*</url-pattern>

In case you are facing this issue recently you should note the following:如果您最近遇到此问题,则应注意以下事项:

If you are using servlet 3.0+ and tomcat > 7.0.43 or Tomcat 8 there are no configuration needed, you just have to provide the correct maven dependencies to make log4j2 aware of running in a webcontainer like the following (in addition we use slf4j):如果您使用的是 servlet 3.0+ 和 tomcat > 7.0.43 或 Tomcat 8,则不需要配置,您只需要提供正确的 maven 依赖项即可让 log4j2 知道在如下所示的 webcontainer 中运行(另外我们使用 slf4j) :

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.0</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.0</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-web</artifactId>
    <version>2.11.0</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.11.0</version>
</dependency>

Since in our case the log4j-web artifact was missing we faced the same warning which said "... started a thread named [AsyncAppender-AsyncFile] but has failed to stop it ..."由于在我们的案例中缺少 log4j-web 工件,因此我们面临相同的警告,该警告说“......启动了一个名为 [AsyncAppender-AsyncFile] 的线程,但未能阻止它......”

After providing the mentioned dependencies the warning is gone.提供上述依赖项后,警告消失了。

you can read more about requirements here您可以在此处阅读有关要求的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM