android 文件句柄,MappedByteBuffer文件句柄释放问题(示例代码)

本文探讨了Java中使用MappedByteBuffer进行文件映射时,文件句柄释放的问题。通过分析,指出即使调用FileChannel的force和close方法,文件仍可能因句柄未释放而无法重命名或删除。解决方案包括利用反射调用FileChannelImpl的unmap方法或自定义unmap方法。在确保文件句柄正确释放后,可以成功进行文件重命名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

现在很多java代码中都会用到内存映射的概念。文件映射的方法比输入输出流的方式快很多。但是在使用的过程中,正常地调用了FileChannel的force和close方法后,重命名文件或删除文件还会失败。主要原因还是文件的句柄没有释放。导致的

问题分析及解决

文件句柄如果被持有,就相当于jvm虚拟机中有一个指向文件的指针,所以重命名文件和删除文件都会导致失败。而MappedByteBuffer没有提供unmap方法,且JDK中关于这个unmap方法的bug一直处于开放状态。在网上查找说的最多的就是利用反射调用FileChannelImpl的unmap方法释放内存:

private static void unmap(MappedByteBuffer var0) {

Cleaner var1 = ((DirectBuffer)var0).cleaner();

if (var1 != null) {

var1.clean();

}

}

反射调用的代码不在写了。而且亲自测试了的确可以保证文件的删除。

利用反射调用的原因是这个方法时私有静态的。但是换一个思路,既然已经知道了内部代码的实现,不如自己写一个unmap方法将内部的代码copy出来不是更好吗?所以

private void unmap(MappedByteBuffer var0) {

Cleaner var1 = ((DirectBuffer)var0).cleaner();

if (var1 != null) {

var1.clean();

}

}

在调用buffer的force方法后,在调用该unmap方法,就可以重命名文件了。

File file = new File(rootPath + fileNum + ".txt");

RandomAccessFile raf = new RandomAccessFile(file,"rw");

FileChannel channel = raf.getChannel();

MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE,0L,numCount * 4);

buffer.force();

channel.force(true);

channel.close();

raf.close();

unmap(buffer)

可以使用rename()方法测试,文件是否被占用

file.rename(file)

返回true重命名成功,返回false文件重命名失败。

特殊情况

如果buffer的容量不够用时,需要用channel.map()重新生成一个MappedByteBuffer对象,在映射新buffer之前应该先调用buffer.force()方法和unmap(buffer) 两个方法。否则文件还是不能进行重命名和删除操作。原因应该是原来存在堆中的对象没有被buffer回收,而且还在持有文件的句柄。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值