我正在使用Infinispan缓存来存储值。代码每10分钟写入缓存,缓存大小约为400mb。 它有一个大约2小时的生存时间,最大条目是1600万,虽然目前在我的测试中,条目数量不超过200万左右(我可以通过检查jconsole中的mbeans / metrics来看到这一点)
当我启动jboss时,java堆大小为1.5Gb到2Gb。 jboss最大分配内存的-Xmx设置为4Gb。
当我禁用Infinispan缓存时,堆内存使用率保持在1.5Gb到2Gb左右。它非常稳定并保持在那个水平。
=>问题是:当我启用Infinispan缓存 时,java堆大小增加到大约3.5Gb / 4Gb,这比预期的要多。 我已经完成了一个堆转储来检查Eclipse MAT中缓存的大小,它只有300或400mb(这没关系)。 所以我希望内存使用量达到2.5Gb并保持稳定在那个级别,因为初始堆大小是2Gb,最大缓存大小应该只有500mb左右。
然而,随着时间的推移,它会继续增长和增长。每2或3小时进行一次垃圾收集,使用量降至约1或1.5Gb,然后在30分钟内再次增加到3.5Gb。 条目数保持稳定在200万左右,因此不是因为只有更多条目进入缓存。 (驱逐的数量也保持在0)。
如果缓存只有400-500mb,那么可以保留多少内存? 我的垃圾收集设置有问题吗?或者我应该看看Infinispan的设置?
谢谢!
编辑:您可以在此处查看堆大小。 奇怪的是,即使看起来像一个完整的GC,内存也会重新回到3Gb。这对应于进入缓存的更多条目。
编辑:事实证明这与Infinispan无关。我将问题缩小到使用大量内存的单行代码(比没有调用大约多1Gb)。 但我确实认为Infinispan缓存会占用越来越多的内存,这自然是因为在2小时内添加了更多的条目。
我还需要在Infinispan上查询超过50个用户。当堆达到这样的高值时(即使没有上面提到的内存泄漏),我知道这不是java中的错误情况,但是我需要尽可能多的内存。 有没有办法“鼓励”堆转储超过某一点?我已经尝试使用GC选项来收集旧代的堆的给定比例,但一般来说堆使用量往往会增加。
答案 0 :(得分:4)
您可能看到的是JVM没有收集已从缓存中逐出的对象。缓存一般与世代GC的流行观念有着奇怪的关系。
世代GC的想法是,从广义上讲,JVM中有两种类型的对象 - 快速使用和丢弃的对象,以及更长寿命的对象,这些对象通常在应用程序的整个生命周期中使用。在此模型中,您希望调整GC,以便将大部分精力用于识别短寿命对象。这意味着您应该尽可能避免查看长寿命对象。
缓存通过拥有一些中等长度的对象生命周期(即几秒/分钟/小时,具体取决于您的缓存)来破坏此模式。这些对象通常被提升为终身代,在完成GC之前,他们通常不会查看这些对象,即使他们已从缓存中逐出。
如果发生了这种情况,那么您有几个选择: