You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Nick Williams <ni...@puresafety.com> on 2012/02/23 01:52:01 UTC

SEVERE: The web application created a ThreadLocal (but I removed it)

I have been getting the ThreadLocal cleanup warning messages appearing in
the Tomcat log for some time now. I finally got around to investigating
these and cleaning it all up. Most of the ThreadLocals I removed, because
they were being abused. However, some needed to hang around, so I used them
more carefully.



Now, at the end of each request, I am calling:



threadLocalInstance.set(null);

threadLocalInstance.remove();



And most of the messages went away. However, a few were still sticking
around. I wanted to track them down, but that’s hard since ThreadLocals
don’t have names. So, I replaced all instances of ThreadLocal in my project
with Spring Framework’s NamedThreadLocal (which simply overrides toString()
to provide better debugging), and here is the resulting log:



Feb 22, 2012 6:21:23 PM org.apache.catalina.loader.WebappClassLoader
clearThreadLocalMap

SEVERE: The web application [/xxx] created a ThreadLocal with key of type
[org.springframework.core.NamedThreadLocal] (value
[GridDataHandler:reminders]) and a value of type [MyPackage.MyClass] (value
[MyPackage.MyClass @1068452]) but failed to remove it when the web
application was stopped. This is very likely to create a memory leak.

Feb 22, 2012 6:21:23 PM org.apache.catalina.loader.WebappClassLoader
clearThreadLocalMap

SEVERE: The web application [/xxx] created a ThreadLocal with key of type
[org.springframework.core.NamedThreadLocal] (value
[GridDataHandler:accidentinvestigation]) and a value of type
[MyPackage.MyClass] (value [MyPackage.MyClass @d92404]) but failed to
remove it when the web application was stopped. This is very likely to
create a memory leak.

Feb 22, 2012 6:21:23 PM org.apache.catalina.loader.WebappClassLoader
clearThreadLocalMap

SEVERE: The web application [/xxx] created a ThreadLocal with key of type
[org.springframework.core.NamedThreadLocal] (value
[GridDataHandler:encounterlisting]) and a value of type [MyPackage.MyClass]
(value [MyPackage.MyClass @1cbad1a]) but failed to remove it when the web
application was stopped. This is very likely to create a memory leak.

Feb 22, 2012 6:21:23 PM org.apache.catalina.loader.WebappClassLoader
clearThreadLocalMap

SEVERE: The web application [/xxx] created a ThreadLocal with key of type
[org.springframework.core.NamedThreadLocal] (value
[GridDataHandler:reminders]) and a value of type [MyPackage.MyClass] (value
[MyPackage.MyClass @d19d73]) but failed to remove it when the web
application was stopped. This is very likely to create a memory leak.



I’m still getting these four messages, and I can’t seem to get them to go
away. But I have tracked down these specific instances and I *am* calling
set(null) and remove() on these instances.



Is something about the Tomcat code somehow locating “phantom” references to
ThreadLocals that have actually been removed and ARE really eligible for
GC, or am I really just not always clearing those ThreadLocals and I just
still haven’t tracked down the source?



Thanks,



Nick



-- 
*Nick Williams |* Senior Software Developer

*UL PureSafety*
Health & Safety Software Solutions

Toll Free: 888.202.3016 x 177  |  Direct: 615.277.3177  |  Fax: 615.367.3887
730 Cool Springs Blvd, Suite 400  |  Franklin, TN 37067  |
www.puresafety.com  |  www.ul.com
------------------------------

*UL acquired PureSafety on December 6, 2011. Learn
More.<http://www.puresafety.com/public/knowledge-exchange/news/2011/12/06/ul-expands-occupational-health-safety-presence-training-capabilit>
*

RE: SEVERE: The web application created a ThreadLocal (but I removed it)

Posted by Nick Williams <ni...@puresafety.com>.
We acquired a product with about a million lines of code. The original
author had no formal software design education and had ported the product
from Pascal to C++ to Java EE. There are many interesting designs in the
code, and no separation of control by any measure. We have a multi-year
roadmap in place to reengineer the software, but it’s going to be a gradual
process, and the transition will involve many temporary “hacks” so to speak.



The use of ThreadLocals in several places helps us achieve the
reengineering in that we can design interfaces now that don’t require us to
pass around some of the “God objects” we’re trying to get rid of, while
still using them in the temporary implementations of these interfaces.
Unfortunately, the use of ThreadLocals was, at first, rather halphazard and
uneducated by some members of the team.



With that said, after spending about another day looking through code,
there really just were a few other places that ThreadLocals were being
set() but not remove()d. I have now resolved all memory leak issues Tomcat
was reporting. This will be followed up by a heavy dose of education for
the team about when it is and isn’t appropriate to use ThreadLocals during
this reengineering phase.



Thanks for responding!



Nick



-- 
*Nick Williams |* Senior Software Developer

*UL PureSafety*
Health & Safety Software Solutions

Toll Free: 888.202.3016 x 177  |  Direct: 615.277.3177  |  Fax: 615.367.3887
730 Cool Springs Blvd, Suite 400  |  Franklin, TN 37067  |
www.puresafety.com  |  www.ul.com
------------------------------

*UL acquired PureSafety on December 6, 2011. Learn
More.<http://www.puresafety.com/public/knowledge-exchange/news/2011/12/06/ul-expands-occupational-health-safety-presence-training-capabilit>
*





-----Original Message-----
From: Christopher Schultz [mailto:chris@christopherschultz.net]
Sent: Sunday, February 26, 2012 8:45 PM
To: Tomcat Users List
Subject: Re: SEVERE: The web application created a ThreadLocal (but I
removed it)



-----BEGIN PGP SIGNED MESSAGE-----

Hash: SHA1



Nick,



On 2/22/12 7:52 PM, Nick Williams wrote:

> Now, at the end of each request, I am calling:

>

> threadLocalInstance.set(null);

>

> threadLocalInstance.remove();



If you are creating a ThreadLocal for each request (that needs the

object) and then disposing of it, why bother with the ThreadLocal in the
first place? Is this a case of wanting global-variable semantics and just
being lazy about (not) passing arguments around?



> I’m still getting these four messages, and I can’t seem to get them to

> go away. But I have tracked down these specific instances and I

> *am* calling set(null) and remove() on these instances.



Does it always happen? Perhaps you are encountering an exception and your
.remove() isn't being called in certain cases. Consider a 'finally' block?



> Is something about the Tomcat code somehow locating “phantom”

> references to ThreadLocals that have actually been removed and ARE

> really eligible for GC, or am I really just not always clearing those

> ThreadLocals and I just still haven’t tracked down the source?



Tomcat just looks at the ThreadLocals still left over in a Thread after
your webapp is stopped. There's nothing "phantom" about them.



- -chris

-----BEGIN PGP SIGNATURE-----

Version: GnuPG/MacGPG2 v2.0.17 (Darwin)

Comment: GPGTools - http://gpgtools.org

Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/



iEYEARECAAYFAk9K7icACgkQ9CaO5/Lv0PBFsgCfT1Y+Mj4C40rwNUAp1wk38e+e

m1IAn22T17lUBZAQ3t9zYBoll5TzEL30

=3Ndj

-----END PGP SIGNATURE-----



---------------------------------------------------------------------

To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org

For additional commands, e-mail: users-help@tomcat.apache.org

Re: SEVERE: The web application created a ThreadLocal (but I removed it)

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nick,

On 2/22/12 7:52 PM, Nick Williams wrote:
> Now, at the end of each request, I am calling:
> 
> threadLocalInstance.set(null);
> 
> threadLocalInstance.remove();

If you are creating a ThreadLocal for each request (that needs the
object) and then disposing of it, why bother with the ThreadLocal in
the first place? Is this a case of wanting global-variable semantics
and just being lazy about (not) passing arguments around?

> I’m still getting these four messages, and I can’t seem to get them
> to go away. But I have tracked down these specific instances and I
> *am* calling set(null) and remove() on these instances.

Does it always happen? Perhaps you are encountering an exception and
your .remove() isn't being called in certain cases. Consider a
'finally' block?

> Is something about the Tomcat code somehow locating “phantom”
> references to ThreadLocals that have actually been removed and ARE
> really eligible for GC, or am I really just not always clearing
> those ThreadLocals and I just still haven’t tracked down the
> source?

Tomcat just looks at the ThreadLocals still left over in a Thread
after your webapp is stopped. There's nothing "phantom" about them.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk9K7icACgkQ9CaO5/Lv0PBFsgCfT1Y+Mj4C40rwNUAp1wk38e+e
m1IAn22T17lUBZAQ3t9zYBoll5TzEL30
=3Ndj
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org