Java 使用静态字典作为缓存可能导致泄漏问题?

Java 使用静态字典作为缓存可能导致泄漏问题?,java,arrays,memory-leaks,garbage-collection,hashmap,Java,Arrays,Memory Leaks,Garbage Collection,Hashmap,我正在处理的web应用程序(servlet)中存在内存泄漏。我怀疑一个原因,想听听你的想法 我使用hashmaps、HashSet等作为DB(加载了大约20MB的数据)。这些地图、集合每10分钟重新加载一次。同时有大量的请求。我读到,GC将在一个时间段/周期内未收集的对象传递给一代(旧代和永久代),该代较少检查或垃圾收集。我认为我对静态贴图集的使用导致了我的泄漏问题。你认为呢?静态地图是已知的泄漏源。原因是人们把东西放进去而不把它们拿走。如果每十分钟您只需清除缓存,然后重新加载,那么您应该没事

我正在处理的web应用程序(servlet)中存在内存泄漏。我怀疑一个原因,想听听你的想法


我使用hashmaps、HashSet等作为DB(加载了大约20MB的数据)。这些地图、集合每10分钟重新加载一次。同时有大量的请求。我读到,GC将在一个时间段/周期内未收集的对象传递给一代(旧代和永久代),该代较少检查或垃圾收集。我认为我对静态贴图集的使用导致了我的泄漏问题。你认为呢?

静态地图是已知的泄漏源。原因是人们把东西放进去而不把它们拿走。如果每十分钟您只需清除缓存,然后重新加载,那么您应该没事


我敢打赌你没有把它清理干净。GC部分工作正常,我不担心这是问题所在。

静态映射是已知的泄漏源。原因是人们把东西放进去而不把它们拿走。如果每十分钟您只需清除缓存,然后重新加载,那么您应该没事


我敢打赌你没有把它清理干净。GC部分工作正常,我不担心这是问题。

如果你有一种方法返回到实际数据,如果你的缓存的一部分是GC,但随后需要的话,你也可以考虑使用。你也可以考虑使用,如果你有一种回落到真实数据的方法,如果你的缓存的一部分是GC,但是随后需要。

如Romain所述,静态地图是可疑的。如果由于某种原因,你不能定期清理它,你可以考虑用A代替,这是

具有弱键的基于哈希表的映射实现。WeakHashMap中的条目在其密钥不再正常使用时将自动删除。更准确地说,给定密钥映射的存在不会阻止垃圾收集器丢弃该密钥,也就是说,使其可终结、终结,然后回收。当一个键被丢弃时,它的条目将被有效地从映射中删除,因此这个类的行为与其他映射实现有所不同


不幸的是,从Java6开始,标准库中似乎没有WeakHashSet,但是可以在网络上找到一些实现。

正如Romain所指出的,静态映射是可疑的。如果由于某种原因,你不能定期清理它,你可以考虑用A代替,这是

具有弱键的基于哈希表的映射实现。WeakHashMap中的条目在其密钥不再正常使用时将自动删除。更准确地说,给定密钥映射的存在不会阻止垃圾收集器丢弃该密钥,也就是说,使其可终结、终结,然后回收。当一个键被丢弃时,它的条目将被有效地从映射中删除,因此这个类的行为与其他映射实现有所不同


不幸的是,从Java6开始,标准库中似乎没有WeakHashSet,但是可以在网络上找到几个实现。

如果删除了对它的所有引用,就不是泄漏。如果你正在彻底清理地图,那么它就不是泄漏的源头。你应该考虑的事实是JVM选择不与GC无关的一代经常与你无关——最重要的是你没有对它的引用,所以JVM可以在需要的时候对它进行GC。 JVM可以使用不同的策略来管理GC,因此我在这里讲的是一般性的而不是具体的,但是GCing终身空间往往非常昂贵,并且对应用程序有很大影响,因此JVM通常选择不这样做

如果您查看使用的堆空间量,您将看到在添加和最终收集项时出现锯齿模式。不要担心锯齿的顶部在哪里,而要关心底部在哪里(以及离最大可用堆空间有多近)


测试它是否真的是泄漏的一种方法是长时间加载测试你的应用程序。如果你有漏洞,你的应用程序使用的基本内存量会随着时间的推移而增加(锯齿的底部)。如果不这样做,它将保持不变。如果确实存在泄漏,可以使用探查器帮助查找。

如果删除了对它的所有引用,则它不是泄漏。如果你正在彻底清理地图,那么它就不是泄漏的源头。你应该考虑的事实是JVM选择不与GC无关的一代经常与你无关——最重要的是你没有对它的引用,所以JVM可以在需要的时候对它进行GC。 JVM可以使用不同的策略来管理GC,因此我在这里讲的是一般性的而不是具体的,但是GCing终身空间往往非常昂贵,并且对应用程序有很大影响,因此JVM通常选择不这样做

如果您查看使用的堆空间量,您将看到在添加和最终收集项时出现锯齿模式。不要担心锯齿的顶部在哪里,而要关心底部在哪里(以及离最大可用堆空间有多近)


测试它是否真的是泄漏的一种方法是长时间加载测试你的应用程序。如果你有漏洞,你的应用程序使用的基本内存量会随着时间的推移而增加(锯齿的底部)。如果不这样做,它将保持不变。如果确实存在泄漏,可以使用探查器帮助查找。

我建议您使用堆转储和堆分析器(例如)检查堆内容。这将帮助您找到泄漏嫌疑犯。事实上,老一代被收集的频率较低并不意味着更多的内存正在泄漏;