严重的番石榴内存泄漏 - 需要解决方法

2022-09-02 22:15:12

有没有办法解决缓存组件中的Google Guava r15内存泄漏(链接到错误报告)

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


答案 1

我想你不需要关心它。雄猫消息说

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

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

详:线程池的原因是线程创建的成本很高。池化本身是黑客,因为你得到一个线程正在做其他事情,线程不是无状态的。线程创建是昂贵的,假设你需要很多线程并且从不回收它们。每隔几分钟更新所有线程没有错,所以我希望,Tomcat的解决方法可以完美地解决它。但事实并非如此。

编辑

恐怕,我误解了什么。链接的错误说

似乎使用番石榴缓存的Web应用程序可能会面临内存泄漏。经过多次重新部署后,应用程序容器崩溃或停止,并出现“内存不足”错误。

我以为Tomcat可以很容易地解决它,但无论出于何种原因,它都不是。所以恐怕,你必须自己打扫。这很容易通过反射实现,所涉及的字段是并且可能是。这是一个糟糕的黑客攻击,更难的部分是当没有任何问题时(即,当没有加载应用程序时)发生这种情况。ThreadLocalThread.threadLocalsinheritableThreadLocals

编辑 2 和 3

我想做这样的事情是安全的

Stripped64.threadHashCode = new ThreadHashCode();

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

作为通过线程存储数据(而不是使用真实线程)来工作,您必须遍历所有线程并删除其中的引用。愚弄其他线程的私有字段是一个可怕的想法,因为它们不是线程安全的,也是由于可见性问题。ThreadLocalMap<Thread, Something>

另一件可能或可能不起作用的事情是我在问题页面上的建议。这只是一个20线补丁。或者只是等待,问题已在昨天分配。

编辑 4

不使用的线程局部变量不会导致任何问题。AFAIK 此 TL 的唯一用途是在缓存统计信息中。因此,请避免两者,并且不会加载。CacheBuilder.recordStatsCache.statsStripped64

编辑 5

看起来它最终会得到解决。从问题中:

道格为我们修复了这个上游,我们把它修补回番石榴:http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9

乍一看,他的变化似乎与我相同。

编辑 6

最后,这已被标记为固定,并宣布了番石榴18.0-rc1。可悲的是,考虑到变化与我(9个月前)相同,花了这么长时间。


答案 2

您可以使用 ServletListener ClassLoaderLeakPreventor https://github.com/mjiderhamn/classloader-leak-prevention/ 它也会在取消部署/停止时清除 ThreadLocals。它还具有针对其他常见泄漏的修复/解决方法。


推荐