`
coderplay
  • 浏览: 571312 次
  • 性别: Icon_minigender_1
  • 来自: 广州杭州
社区版块
存档分类
最新评论

文件在使用FileChannel.map后不能被删除(Windows上)

    博客分类:
  • java
阅读更多
同事发现在Windows上使用FileChannel的map方法之后, 不能够删除掉文件. 我在Linux上试了一下, 发现没这个问题。 做个笔记, 记录一下.
import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
 
import sun.nio.ch.FileChannelImpl;
 
public class TestDeleteMappedFile {

  public static void main(String args[]) {
    File f = new File("mapfile");
    RandomAccessFile aFile = null;
    FileChannel inChannel = null;
    try {
      aFile = new RandomAccessFile(f, "rw");
      inChannel = aFile.getChannel();
      ByteBuffer buf = inChannel.map(MapMode.READ_WRITE, 0L, 4);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        inChannel.close();
        aFile.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    System.out.println("delete " + f + " : " + f.delete());
  }
}


Oracle的buglist上看到了这个问题的描述.

引用

We cannot fix this.  Windows does not allow a mapped file to be deleted.  This
problem should be ameliorated somewhat once we fix our garbage collectors to
deallocate direct buffers more promptly (see 4469299), but otherwise there's
nothing we can do about this.


sun.misc.Cleaner为我们干了关闭文件, 释放资源的脏活. 这个类是一个幻引用, 所以会在gc的时候调用到. FileChannel正是调用了这个Cleaner, 在gc的时候做unmap.


// sun.nio.ch.FileChannelImpl类
 Unmapper um = new Unmapper(addr, size + pagePosition);
            if ((!writable) || (imode == MAP_RO))
                return Util.newMappedByteBufferR(isize, addr + pagePosition, um);

// java.nio.DirectByteBuffer类
    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
    //
    protected DirectByteBuffer(int cap, long addr, Runnable unmapper) {

        super(-1, 0, cap, cap, true);
	address = addr;
	cleaner = Cleaner.create(this, unmapper);
        viewedBuffer = null;



    }


如果finalizer delay的时候不能调unmap, 那么手动调unmap, 应该就可以在windows上释放掉资源了. 我们试试

import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
 
import sun.nio.ch.FileChannelImpl;
 
public class TestDeleteMappedFile {

  public static void main(String args[]) {
    File f = new File("mapfile");
    RandomAccessFile aFile = null;
    FileChannel inChannel = null;
    try {
      aFile = new RandomAccessFile(f, "rw");
      inChannel = aFile.getChannel();
      ByteBuffer buf = inChannel.map(MapMode.READ_WRITE, 0L, 4);
      // 加上这几行代码,手动unmap
      Method m = FileChannelImpl.class.getDeclaredMethod("unmap", MappedByteBuffer.class);
      m.setAccessible(true);
      m.invoke(FileChannelImpl.class, buf);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        inChannel.close();
        aFile.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    System.out.println("delete " + f + " : " + f.delete());
  }
}


果然, 可以删除

Have fun!
分享到:
评论
3 楼 bohc 2018-03-29  
谢谢,搞了两天了,现在才算是找到问题所在,解决了。
2 楼 zhangyifan_614 2013-03-01  
感觉反射调用Cleaner的clean方法会更好些!
因为他可以封装包括unmap在内的所有释放资源的操作!
1 楼 huijie 2013-02-27  
也碰到相同问题了

相关推荐

    flume中的FileChannel的优化

    经过对Flume FileChannel相关源码的分析,导致FileChannel吞吐率下降的主要原因集中于事务的提交过程——commit

    【IT十八掌徐培成】Java基础第26天-06.FileChannel-RandomAccessFile-CopyFile.zip

    【IT十八掌徐培成】Java基础第26天-06.FileChannel-RandomAccessFile-CopyFile.zip

    编写一个java应用程序将一个包含多个子目录和文件的目录复制到另外一个指定的目录下

    1)欲复制的目录中包含的文件数和子目录层次未知,必须在程序执行时获得这些信息。 2)显示欲复制的目录的相关信息。 程序模块 import java.io.BufferedReader; import java.io.File; import java.io....

    NIO(byteBuffer)按行读取文件

    使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com

    muyinchen#woker#07 Java的NIO之FileChannel1

    7.1 打开一个FileChannel 7.2 从FileChannel通道中读取数据 7.3 向FileChannel中写入数据: 7.4 关闭FileCha

    java高效文件复制.txt

    在Java编程中,复制文件的方法有很多,而且经常要用到...我以前一直是缓冲输入输出流来实现的(绝大多数人都是如此),近来在研究JDK文档时发现,用文件通道(FileChannel)来实现文件复制竟然比用老方法快了近三分之一

    kafka & mafka client开发与实践

    首先,kafka的开发者们认为不需要在内存里缓存什么数据,操作系统的文件缓存已经足够完善和强大,只要你不搞随机写,顺序读写的性能是非常高效的。kafka的数据只会顺序append,数据的删除策略是累积到一定程度或者...

    javaSE 关于IO几种读取方式的性能比较

    javaSE 关于IO几种读取方式的性能比较 1.二进制数据 2.字符数据 3.压缩文件

    java网络编程NIO视频教程

    01-Java NIO-课程简介.mp4 02-Java NIO-概述.mp4 03-Java NIO-Channel-概述.mp4 ...13-Java NIO-Buffer-基本使用.mp4 14-Java NIO-Buffer-三个属性和类型.mp4 15-Java NIO-Buffer-分配和读写数据.mp4

    Java NIO实战开发多人聊天室

    13-Java NIO-Buffer-基本使用.mp4 14-Java NIO-Buffer-三个属性和类型.mp4 17-Java NIO-Buffer-缓冲区分片.mp4 18-Java NIO-Buffer-只读缓冲区.mp4 19-Java NIO-Buffer-直接缓冲区.mp4 21-Java NIO-Selector-概述....

    txt文档阅读器

    m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map( FileChannel.MapMode.READ_ONLY, 0, lLen); //RandomAccessFile是用来访问那些保存数据记录的文件的 } //读一段 protected byte[]...

    jruby-stdin-channel:JRuby 扩展为 STDIN 公开可中断的 NIO FileChannel

    使用这个 gem,在阻塞read方法上调用close将解除阻塞,这与普通的 JRuby $stdin 。 使用close转义阻塞读取仅适用于 Java 8 。 使用 Java 7 时,其行为与普通 JRuby $stdin相同,其中需要键入输入字符才能解锁 read ...

    jdk-14_linux-x64_bin.rpm

    非易失性映射的字节缓冲将添加新的 JDK 特定文件映射模式,该模式允许 FileChannel API 用于创建引用非易失性内存(NVM)的 MappedByteBuffer 实例。 358:Helpful NullPointerExceptions 改进 ...

    java 工具包 h264转码MP4 支持html5播放格式

    H264TrackImpl h264TrackImpl = new H264TrackImpl(new ... FileChannel fChannel = new FileOutputStream(new File("C://a.mp4")).getChannel(); mp4f.writeContainer(fChannel); fChannel.close();

    qtfaststart-java:MIT许可的Java中的qt-faststart(使mp4文件可流式传输)

    使用FileChannel#transferTo而不使用String比较。 安装 可从。 repositories { jcenter() } compile 'net.ypresto.qtfaststartjava:qtfaststart:0.1.0' 执照 MIT许可证。 有关原始源代码的信息 该产品基于qt-

    ip地址库 很全的库

    * 为0x1时,表示在绝对偏移后还跟着一个区域的记录,注意是绝对偏移之后,而不是这四个字节之后 b. 为0x2时,表示在绝对偏移后没有区域记录 * 不管为0x1还是0x2,后三个字节都是实际国家名的文件内绝对偏移 * ...

    tomcat-7_API_帮助文档

    6470086: (fc) FileChannel.transferTo(2147483647, 1, channel) cause "Value too large" exception ============================= Enabling SSI and CGI Support: ============================= Because ...

    sambox:一个PDFBox分支,打算用作Sejda和PDFsam的PDF处理程序

    SAMBox PDF处理器 一个分支,打算用作和相关项目的PDF处理器与PDFBox有何不同? 需要JDK8 延迟加载/解析PDF对象。 最初仅解析文档外部参照表/流,并检索到查找... PDF对象可以在写入后立即写入(同步/异步)并丢弃,这

    Java版水果管理系统源码-flume-kafka-storm:大数据实时计算的基础框架

    首先,kafka的开发者们认为不需要在内存里缓存什么数据,操作系统的文件缓存已经足够完善和强大,只要你不搞随机写,顺序读写的性能是非常高效的。kafka的数据只会顺序append,数据的删除策略是累积到一定程度或者...

    卫斯理合集 倪匡

    合并文本代码,读取文件,合并为一个txt public static final int BUFSIZE = 1024 * 8; public static void mergeFiles(String outFile, ArrayList<String> files) { FileChannel outChannel = null; try { ...

Global site tag (gtag.js) - Google Analytics