严重的番石榴内存泄漏 - 需要解决方法 [英] Critical guava memory leak - Workaround needed

查看:32
本文介绍了严重的番石榴内存泄漏 - 需要解决方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么办法可以解决 Google Guava r15 内存泄漏(链接到错误报告) 在缓存组件中?

Is there any way to workaround the Google Guava r15 memory leak (link to the bug report) in the cache component?

(不依赖应用服务器可能会清理和/或考虑 Web 应用程序永远不会重新启动/重新部署)

(Without relying that the application server might clean things up and/or considering that the web application will never be restarted/redeployed)

推荐答案

我想你不需要关心它. Tomcat 消息说

I guess you don't need to care about it. The Tomcat message says

线程将随着时间的推移而更新,以尝试避免可能的内存泄漏.

Threads are going to be renewed over time to try and avoid a probable memory leak.

IIUIC 意味着一旦所有旧线程都消失了,所有指向类的旧版本的指针也将消失.

IIUIC it means that once all old threads are gone, so will all the pointers to the old version of your class.

细节:线程池的原因是线程创建的巨大成本.当你得到一个正在做其他事情的线程并且线程不是无状态的时,池本身是 hacky 的.假设您需要大量线程并且从不回收它们,那么线程创建的成本会很高.每隔几分钟更新所有线程并没有错,所以我希望 Tomcat 的解决方法可以完美解决它.但事实并非如此.

Details: The reason for the thread pooling is the big cost of thread creation. The pooling itself is hacky as you get a thread which was doing something else and thread are not stateless. Thread creation is expensive assuming you'd need a lot of them and never recycle them. There's nothing wrong with renewing all threads every few minutes, so I hoped, Tomcat's workaround solves it perfectly. But it's not the case.

恐怕,我误会了什么.链接的错误说

I'm afraid, I misunderstood something. The linked bug says

似乎使用 guava 缓存的 Web 应用程序可能面临内存泄漏.多次重新部署后,应用程序容器崩溃或停止并出现 OutOfMemoryError.

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.

我认为 Tomcat 可以轻松解决它,但无论出于何种原因,它都没有.所以恐怕你必须自己清理 ThreadLocal .这很容易通过反射实现,相关字段是 Thread.threadLocals 和可能的 inheritableThreadLocals.这是一个糟糕的黑客,更难的部分是在没有任何问题的情况下实现这一点,即当没有加载应用程序时.

I thought Tomcat could solve it easily, but for whatever reason it doesn't. So I'm afraid, you have to clean the ThreadLocals yourself. This is easily possible via reflection, the concerned fields are Thread.threadLocals and possibly inheritableThreadLocals. It's a bad hack and the harder part is to make this happen when nothing can go wrong, i.e., when no application is loaded.

我想这样做是安全的

Stripped64.threadHashCode = new ThreadHashCode();

因为所包含的东西只需要在激烈竞争下的性能,它们会在使用时重新创建.但根据 MRalwasser 的评论,它根本无济于事,因为活动线程仍然会引用旧值.所以似乎没有办法.

as the contained things are only needed for performance under heavy contention and they get recreated upon use. But according to MRalwasser's comment, it won't help at all as alive threads will still refer the old value. So there seem to be no way.

由于 ThreadLocal 通过使用线程存储数据(而不是使用真正的 Map)来工作,因此您必须遍历所有线程并删除参考那里.玩弄其他线程的私有字段是一个糟糕的主意,因为它们不是线程安全的,而且还存在可见性问题.

As ThreadLocal works by storing data with the threads (rather then using a real Map<Thread, Something>), you'd have to through all threads and remove references there. Fooling around with other threads' private fields is a terrible idea as they are not thread-safe and also due to visibility issues.

另一件可能行不通的事情是我对 问题页面.这只是一个 20 行的补丁.或者干脆等一下,这个问题昨天已经分配了.

Another thing that might or mighn't not work is my proposal on the issue page. It's just a 20 line patch. Or simply wait, the issue has been assigned yesterday.

不被使用的线程局部变量不会引起任何问题.AFAIK 此 TL 的唯一用途是缓存统计信息.所以避免 CacheBuilder.recordStatsCache.statsStripped64 不会被加载.

Thread locals which don't get used can't cause any problems. AFAIK the only use of this TL is in cache stats. So avoid both CacheBuilder.recordStats and Cache.stats and Stripped64 won't get loaded.

看起来它最终会得到修复.来自问题:

It looks like it's gonna get fixed finally. From the issue:

Doug 为我们在上游修复了这个问题,我们将其修补回 Guava:http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9

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?revision=1.9

乍一看他的变化 似乎与我的.

最后,这已被标记为固定和 Guava 18.0-rc1 已经公布.鉴于更改与我的相同(9 个月前),所以花了这么长时间真是令人遗憾.

Finally, this has been marked as fixed and Guava 18.0-rc1 has been announced. It's just sad it took that long given that the change is the same as mine (9 month ago).

这篇关于严重的番石榴内存泄漏 - 需要解决方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆