DaveAKing / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Possible classloader leak caused by Striped64 #1553

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
It seems that web applications which are using guava cache might face a memory 
leak.
After several redeployments, the application container crashes or stalls with 
an OutOfMemoryError.

When looking at the corresponding heap dump in these cases it seems that 
something is keeping the web application classloaders alive.
The only GC root to the classloader is the following path:

Class Name                                                     | Shallow Heap | 
Retained Heap
--------------------------------------------------------------------------------
--------------
<classloader> class com.google.common.cache.Striped64$HashCode |            8 | 
           64
|- <class> com.google.common.cache.Striped64$HashCode          |           16 | 
           16
|  '- value java.lang.ThreadLocal$ThreadLocalMap$Entry         |           32 | 
           48
|     '- [9] java.lang.ThreadLocal$ThreadLocalMap$Entry[32]    |          144 | 
          880
|        '- table java.lang.ThreadLocal$ThreadLocalMap         |           24 | 
          904
|           '- threadLocals com.caucho.env.thread2.ResinThread2|          136 | 
        1.296
--------------------------------------------------------------------------------
--------------

(ResinThread2 is just extending java.lang.Thread, so in fact, the GC roots are 
originating from java.lang.Thread.threadLocals)

As you can see, com.google.common.cache.Striped64$HashCode is still referenced 
by a ThreadLocal.
This ThreadLocal and its initial value (which is the Striped64$HashCode 
instance) is created here:

http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/comm
on/cache/Striped64.java?r=d6da7d86a2cab91bb3d33d983ccf5b07de14cc20#144

However, neither the static ThreadLocal (respectively its actual subclass 
ThreadHashCode) nor its value is cleared at any time later.
As a result, as long as the Thread (which created the ThreadLocal) is alive, 
will keep its classloader alive.
For regular applications this might often not be an issue, however, for 
application servers which reuses/shares Threads across web applications this 
will cause classloader leaks.

Original issue reported on code.google.com by patric.r...@gmail.com on 9 Oct 2013 at 1:47

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 9 Oct 2013 at 1:53

GoogleCodeExporter commented 9 years ago
When deploying web applications which use guava cache on tomcat 7 and restart 
it, tomcat's memory leak detection is reporting the issue, too:

SEVERE: The web application [/context] created a ThreadLocal with key of type 
[com.google.common.cache.Striped64.ThreadHashCode] (value 
[com.google.common.cache.Striped64$ThreadHashCode@140980f]) and a value of type 
[com.google.common.cache.Striped64.HashCode] (value 
[com.google.common.cache.Striped64$HashCode@1bf17fe]) 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.

Original comment by patric.r...@gmail.com on 28 Oct 2013 at 4:25

GoogleCodeExporter commented 9 years ago
IIUIC the problem is the chain Thread -> ThreadHashCode -> Striped64$HashCode 
-> class loader. Here the HashCode is nothing but a mutable int holder, so 
maybe int[1] should do. There's still the problem with subclassing ThreadLocal 
and ThreadHashCode.initialValue, which can be solved by handling it manually 
(when get() return null, initialize it with new int[aNonZeroRandomNumber]). 
Just an ugly idea.

Original comment by Maaarti...@gmail.com on 29 Oct 2013 at 6:12

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 29 Oct 2013 at 5:51

GoogleCodeExporter commented 9 years ago
I was asked to propose my patch here, so I'm attaching it. It does exactly what 
I described above.

Original comment by Maaarti...@gmail.com on 7 Nov 2013 at 10:21

Attachments:

GoogleCodeExporter commented 9 years ago
To the developers: half a year passed - any news regarding this?

Original comment by patric.r...@gmail.com on 19 Apr 2014 at 1:44

GoogleCodeExporter commented 9 years ago

Original comment by lowas...@google.com on 29 Apr 2014 at 4:38

GoogleCodeExporter commented 9 years ago

Original comment by kak@google.com on 29 Apr 2014 at 5:08

GoogleCodeExporter commented 9 years ago
Doug fixed this upstream for us and we patched it back into Guava:
http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?r
evision=1.9

Thanks for digging this up!

Original comment by kak@google.com on 6 May 2014 at 3:27

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 5 Aug 2014 at 10:32

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<issue id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:12

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:08