首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java内存缓存

Java内存缓存
EN

Stack Overflow用户
提问于 2021-03-12 15:17:16
回答 3查看 380关注 0票数 0

有没有可能在内存中实现缓存,以避免整个堆的消耗?

我的spring-boot java应用程序使用内存中的缓存,过期策略设置为1小时(Caffeine库用于缓存目的)。在此之后,所有缓存实例都在老一代中,并且需要收集完整的GC。现在将XMX设置为10 in,经过几个小时的测试,我可以看到我的缓存包含了大约100k个实例,但在堆中(正好在老一代),我可以找到数百万个缓存对象的实例。有没有可能在内存中使用缓存并避免这种情况?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-03-12 15:55:29

您所描述的问题称为内存泄漏。

是的,你可以,但这取决于你使用的GC版本。例如,在G1中,这个问题应该不会出现。所以,如果可能的话,我建议你改用G1。

XpauseTarget这个标志是为了避免系统中的长时间停顿,所以你可以将清理堆分成几部分。

您还可以自定义需要运行GC的百分比。-XX:InitiatingHeapOccupancyPercent=45

票数 1
EN

Stack Overflow用户

发布于 2021-03-12 15:57:10

正如您所观察到的,缓存和分代收集器有着截然相反的目标。更现代的收集器,如G1和Shenandoah,是基于区域的,这可以让它们更好地处理旧的gen收集。在Shenandoah的技术讲座中,你会经常听到他们的开发人员讨论LRU缓存作为压力测试。如果您的GC调得很好,这可能不是问题。

您可以将缓存数据结构保留在堆上,但将其条目移走。这可以通过将值序列化为ByteBuffer来实现,代价是访问开销。Apache Mnemonic提供了另一种方法,它将对象字段存储在堆外,并透明地编组数据。这避免了序列化成本,但对对象模型是侵入性的。

有像Oak这样的完全离堆的哈希表和像OHC这样的缓存。这些缓存尽可能地移动到GC之外,但是与堆上缓存相比,有更多的开销。这与使用远程缓存(如memcached或redis )相当,因此可能更可取。例如,Memcached使用存储片分配来非常有效地处理内存流失。

大多数情况下,您将看到小型堆上缓存用于快速本地访问最常用的数据,而大型远程缓存则为其他所有数据提供支持。如果您确实需要多GB的进程内缓存,那么可能有必要使用堆外缓存,或者您可能需要调优GC来适应此工作负载。

票数 0
EN

Stack Overflow用户

发布于 2021-03-12 15:59:39

如果未设置过期时间,则缓存中的对象始终存在。你可以做的就是调优JVM来避免这种情况,也就是说,如果你使用的是CMS,-XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly,设置了这两个选项,JVM就会被强制执行完整的gc,而老一代的gc超过75%。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66595767

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档