截断内存映射文件

截断内存映射文件

本文介绍了截断内存映射文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using memory mapped IO for an index file, but the problem is that I'm not able to resize the file if it is mostly empty.

之前的某个地方:

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

调整大小:

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生产环境中,一切似乎都没有警告,但文件保持原始大小。

When using Windows or Linux 32-bit I often have the unmapping problem, but in the 64 bit Linux production environment everything seems to work without warnings, but the file keeps the original size.

任何人都可以解释为什么会发生这种情况和/或者如何解决问题?

Can anyone explain why this happens and/or how to solve the problem?

推荐答案

您的问题是您使用不可靠的方法来关闭映射的字节缓冲区(一百个调用)到 System.gc() System.runFinalization()不保证任何东西)。遗憾的是,Java API中没有可靠的方法可以做到这一点,但是在Sun JVM上(也可能在其他一些方面),您可以使用以下代码:

Your issue is that you are using unreliable method to close mapped byte buffer (one hundred calls to System.gc() and System.runFinalization() don't guarantee you anything). Unfortunately there is no reliable method in Java API to do that, but on Sun JVM (and perhaps on some others too) you can use the following code:

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 sun.misc.Cleaner ,请准备修复您的代码以不相容的方式(但实际上我不相信这种情况会发生)。

Of course it is JVM-dependent and you should be ready to fix your code if Sun ever decides to change sun.nio.ch.DirectBuffer or sun.misc.Cleaner in an incompatible manner (but actually I don't believe this will ever happen).

这篇关于截断内存映射文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 16:39