New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible classloader leak caused by Striped64 #1553
Comments
Original comment posted by cgdecker@google.com on 2013-10-09 at 01:53 PM (No comment entered for this change.) Labels: |
Original comment posted by patric.rufflar on 2013-10-28 at 04:25 PM 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 posted by Maaartinus on 2013-10-29 at 06:12 AM 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 posted by cgdecker@google.com on 2013-10-29 at 05:51 PM (No comment entered for this change.) Owner: lowasser@google.com |
Original comment posted by Maaartinus on 2013-11-07 at 10:21 PM I was asked to propose my patch here, so I'm attaching it. It does exactly what I described above. |
Original comment posted by patric.rufflar on 2014-04-19 at 01:44 PM To the developers: half a year passed - any news regarding this? |
Original comment posted by lowasser@google.com on 2014-04-29 at 04:38 PM (No comment entered for this change.) |
Original comment posted by kak@google.com on 2014-04-29 at 05:08 PM (No comment entered for this change.) CC: dl@cs.oswego.edu |
Original comment posted by kak@google.com on 2014-05-06 at 03:27 PM Doug fixed this upstream for us and we patched it back into Guava: Thanks for digging this up! Status: |
Original comment posted by cgdecker@google.com on 2014-08-05 at 10:32 PM (No comment entered for this change.) Labels: |
Original issue created by patric.rufflar on 2013-10-09 at 01:47 PM
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:
guava/guava/src/com/google/common/cache/Striped64.java
Line 144 in d6da7d8
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.
The text was updated successfully, but these errors were encountered: