struts-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rene Gielen (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (WW-4058) ContainerHolder causes ThreadLocal memory leak
Date Thu, 25 Apr 2013 16:26:16 GMT

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

Rene Gielen edited comment on WW-4058 at 4/25/13 4:25 PM:
----------------------------------------------------------

Lukasz, your patch won't work since the ContainerHolder-ThreadLocal is bound per request thread,
while the destroy method is bound to the shutdown thread which most likely never served a
request before. Thus you will not be clearing the actual request ThreadLocal instances in
the destroy phase when calling clear.

That said, we need to cleanup those ThreadLocals by the end of the request. To me best candidate
seems to be Dispatcher.cleanupRequest. I'm not entirely sure this gets called no matter what,
though. A bit annoying when dealing with ThreadLocals like these is the lazy initialization
via Dispatcher.getContainer, which has a massive call hierarchy. Usually we would want to
have ThreadLocals initialized with a predictable lifecycle, that is init exactly once at the
beginning and destroy guarantied exactly once at the end of the cycle. Also I'm wondering
if we would better be off to use the Request to store the Container rather than a ThreadLocal.
But I'm not sure about the implication at that stage.

Anyway, to clean up ThreadLocals we should call remove() (since 1.5) rather than set null.
I'm going to change this now as a first yet unimportant step
                
      was (Author: rgielen):
    Lukasz, your patch won't work since the ContainerHolder-ThreadLocal is bound per request
thread, while the destroy method is bound to the shutdown thread which most likely never served
a request before. Thus you will not be clearing the actual request ThreadLocal instances in
the destroy phase when calling clear.

That said, we need to cleanup those ThreadLocals by the end of the request. To me best candidate
seems to be Dispatcher.cleanupRequest. I'm not entirely sure this gets called no matter what,
though. A bit annoying when dealing with ThreadLocals like these is the lazy initialization
via Dispatcher.getContainer, which has a massive call hierarchy. Usually we would want to
have ThreadLocals initialized with a predictable lifecycle, that is init exactly once at the
beginning and destroy guarantied exactly once at the end of the cycle. Also I'm wondering
if we would better be off to use the Request to store the Container rather than a ThreadLocal.
But I'm not sure about the implication at that stage.

Anyway, to clean up ThreadLocals we should call remove() (since 1.6) rather than set null.
I'm going to change this now as a first step
                  
> ContainerHolder causes ThreadLocal memory leak
> ----------------------------------------------
>
>                 Key: WW-4058
>                 URL: https://issues.apache.org/jira/browse/WW-4058
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Actions
>    Affects Versions: 2.3.14
>         Environment: Tomcat 7.0.39
> java version "1.7.0_15"
> OpenJDK Runtime Environment (IcedTea7 2.3.7) (7u15-2.3.7-0ubuntu1~12.04.1)
> OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
>            Reporter: Boris Morris
>            Assignee: Lukasz Lenart
>             Fix For: 2.3.15
>
>         Attachments: hprof_2.png, hprof.png
>
>
> The localContext ThreadLocal is not cleaned up properly when stopping / undeploying /
redeploying a S2 application. This will in most cases cause the web application ClassLoader
not to be garbage collected, thus leaving a redeployment memory leak.
> I am using Tomcat 7.0.39 and when I undeploy my application the following is reported
in the logs:
> {noformat}
> 2013-04-23 12:00:31,082 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,083 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,101 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,101 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,101 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,101 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,102 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,102 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,103 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,103 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,103 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> 2013-04-23 12:00:31,103 [request-worker-4] ERROR org.apache.catalina.loader.WebappClassLoader-
The web application [/dev] created a ThreadLocal with key of type [java.lang.ThreadLocal]
(value [java.lang.ThreadLocal@7f2283e1]) and a value of type [com.opensymphony.xwork2.inject.ContainerImpl]
(value [com.opensymphony.xwork2.inject.ContainerImpl@330069fc]) but failed to remove it when
the web application was stopped. Threads are going to be renewed over time to try and avoid
a probable memory leak.
> {noformat}
> After poking around in the heap dump it would seem that Tomcat is correct. There is indeed
a GC root at the ThreadLocal used by the ContainerImpl.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Mime
View raw message