截断内存映射文件

2024-03-12

我正在对索引文件使用内存映射 IO,但问题是如果文件大部分为空,我无法调整文件大小。

之前的某个地方:

MappedByteBuffer map = raf.getChannel().map(MapMode.READ_WRITE, 0, 1 << 30);
raf.close();
// use map
map.force();
map = null;

Resize:

for (int c = 0; c < 100; c++) {
    RandomAccessFile raf = new RandomAccessFile(indexFile, "rw");
    try {
        raf.setLength(newLen);
        if (c > 0) LOG.warn("used " + c + " iterations to close mapped byte buffer");
        return;
    } catch (Exception e) {
        System.gc();
        Thread.sleep(10);
        System.runFinalization();
        Thread.sleep(10);
    } finally {
        raf.close();
    }
}

当使用 Windows 或 Linux 32 位时,我经常遇到取消映射问题,但在 64 位 Linux 生产环境中,一切似乎都正常运行,没有警告,但文件保持原始大小。

谁能解释为什么会发生这种情况和/或如何解决问题?


您的问题是您正在使用不可靠的方法来关闭映射的字节缓冲区(对System.gc() and System.runFinalization()不向你保证任何事情)。不幸的是,Java API 中没有可靠的方法来做到这一点,但在 Sun JVM(也许还有其他一些)上,您可以使用以下代码:

public void unmapMmaped(ByteBuffer buffer) {
  if (buffer instanceof sun.nio.ch.DirectBuffer) {
    sun.misc.Cleaner cleaner = ((sun.nio.ch.DirectBuffer) buffer).cleaner();
    cleaner.clean();
  }
}

当然,它依赖于 JVM,如果 Sun 决定更改,您应该准备好修复您的代码sun.nio.ch.DirectBuffer or sun.misc.Cleaner以不兼容的方式(但实际上我不相信这会发生)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

截断内存映射文件 的相关文章

随机推荐