3

我正在运行一个使用 Ehcache 3.4.0 的 Web 应用程序。我有一个缓存配置,它定义了 1000 个内存对象的简单默认值:

<cache-template name="default">
    <key-type>java.lang.Object</key-type>
    <value-type>java.lang.Object</value-type>
    <heap unit="entries">1000</heap>
</cache-template>

然后,我有一些使用此默认模板的基于磁盘的缓存,但会覆盖所有值(以编程方式生成,所以这就是他们甚至使用默认模板的原因),如下所示:

<cache alias='runViewCache' uses-template='default'>
    <key-type>java.lang.String</key-type>
    <value-type>java.lang.String</value-type>
    <resources>
        <heap unit='entries'>1</heap>
        <disk unit='GB' persistent='true'>1</disk>
    </resources>
</cache>

当数据写入我的基于磁盘的缓存时,JVM 使用直接/堆外内存,并且从未释放。即使清除缓存也不会释放内存。使用的内存与写入基于磁盘的缓存的数据直接相关(据我所知,几乎是逐个字节)。

此缓存的权威层是org.ehcache.impl.internal.store.disk.OffHeapDiskStore的一个实例。

这似乎是内存泄漏(内存被消耗且从未释放),但我绝不是配置 ehcache 的专家。任何人都可以建议进行配置更改以导致我的磁盘层不使用堆外内存吗?或者,我是否完全误解了其他人可以指出的其他内容?

谢谢!

4

1 回答 1

2

你如何衡量“使用”?

TL;DR 不,磁盘层不会浪费 RAM。

v3.0.0 开始, Ehcache 使用内存映射文件进行磁盘持久性:

将 Ehcache 2.x 开源磁盘存储的端口替换为利用堆外库和内存映射文件的端口。

这意味着,Ehcache 使用内存地址空间来访问磁盘上的文件。这确实会消耗 0 字节的 RAM。(至少直接。正如@louis-jacomet 已经说过的那样,操作系统可以决定将部分文件缓存在 RAM 中。)

在 Linux 上运行时,您应该比较进程的 VIRT 和 RES 值。VIRT 是进程使用的虚拟字节数。RES 是进程使用的实际 RAM (RESident) 字节的数量。VIRT 应该增加,而磁盘存储缓存被填充,但 RES 应该保持相当稳定。

于 2017-11-14T13:15:14.157 回答