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

2023-11-16

同事发现在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());
}
}


从[url=http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154]Oracle的buglist[/url]上看到了这个问题的描述.

[quote]
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.
[/quote]

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

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

随机推荐

  • 半波整流、全波整流电路#集成运算放大器

    半波整流 全波整流电路 集成运算放大器
  • 一零六八、回顾MySQL关键字排序

    一 关键字书写顺序 select distinct from join on where group by having union all order by limit 二 关键字实际执行顺序 from on join where gro
  • 详解Spring Bean的生命周期

    Spring Bean的生命周期是Spring面试热点问题 这个问题即考察对Spring的微观了解 又考察对Spring的宏观认识 想要答好并不容易 本文希望能够从源码角度入手 帮助面试者彻底搞定Spring Bean的生命周期 只有四个
  • 通过一张照片来定位拍摄地点和网站的域名 LA CTF 2023

    简介 这次打ctf遇到了一个比较经典的osint类题目 在这里分享一下如何做此类题目 题目链接 https platform lac tf challs 题目简介 你能猜出这个猫天堂的名字吗 答案是此位置的网站域 例如 如果答案是 ucla
  • 从编译器角度分析C语言中数组名和指针的区别

    数组名和指针是两个往往很容易让人们混淆的概念 很多人以为数组名就是一个指针 也有很多人知道数组名不同于指针但是仅知道数组名的值不能像指针一样改变 例如你可以写出下面这样的代码 int p p 却不能写这样的代码 int a a 那么数组名跟
  • Ubuntu下GCC引用mysql头文件和库文件

    http blog csdn net fjssharpsword article details 6942812 1 安装mysql server sudo apt get install mysql server 5 1 2 gcc连接m
  • 小程序嵌套h5界面,在h5界面调用小程序的扫一扫功能(自用方法3)

    前言 因为小程序对项目要求比较多 我们经常会使用webview嵌套H5界面来 然后在H5界面来实现我们的一些功能页面 这里就会遇到一些问题 比如H5界面的微信扫码功能 目录 实现方法的尝试 自用方法3 方法1 在h5界面中 点击调用小程序的
  • Go语言的学习【2】基础语法

    目录 代码组成部分 字符串 格式化字符 数据类型 变量 变量声明 多变量声明 值类型和引用类型 遇到的问题及解决办法 1 报错1 代码组成部分 Go 程序可以由多个标记组成 可以是关键字 标识符 常量 字符串 符号 在 Go 程序中 一行代
  • Python编程快速入门基础作品(集合)

    Python编程快速入门基础作品 第1集线条 Python编程快速入门基础作品 第2集角 Python编程快速入门基础作品 第3集三角形 Python编程快速入门基础作品 第4集正方形 Python编程快速入门基础作品 第5集五边形 Pyt
  • c语言实现队列

    1 队列的定义 队列 queue 是只允许在一端进行插入操作 而在另一端进行删除操作的线性表 队列是一种先进先出 First In First Out 的线性表 简称FIFO 允许插入的一端称为队尾 允许删除的一端称为队头 队头 head
  • c++ stl(标准模板库)

    1 引言 STL 标准模板库 从广义上分为 容器 算法 迭代器 容器和算法之间通过迭代器进行无缝连接 在 c 标准种 STL被组织成以下13个头文件
  • qt多线程下,QString赋值导致崩溃

    问题 在多线程情况下 给全局的QString变量赋值 拷贝操作 导致程序崩溃 例如有一个全局变量 QString strGlobal 在多线程代码段中进行赋值 strGlobal QString real value 线程执行频率到一定程度
  • 乐学python靠谱吗_【乐学100】-乐学100怎么样

    花开梦未蓝nice 今天刚给孩子注册成功 孩子马上被乐学100吸引住了 首先 是看到礼品店里有许多他心仪的奖品 他希望通过努力能够得到礼品 然后 他开始为自己挣学分 他一口气做了有理数单元11个小模块的练习 正确率较高 又做了错题总结 改正
  • C++函数模板基础

    今天给大家带来函数模板的内容 当我们面对 逻辑相同但类型不同 的问题时 比如整型相加和浮点型相加 使用函数模板可以提高代码利用率 起到事半功倍的效果 今天给大家分享蛋类型变量的函数模板 include
  • 关于C++对象模型(下)

    下篇主要讨论调用成员函数 访问成员变量的开销 及其特殊成员函数 数组 异常处理的讨论 这篇文章中出现的对象定义都出现在上篇中 全文在这里下载 文章内容转自 http tb blog csdn net TrackBack aspx PostI
  • 数据链路层六大协议详解

    数据链路层六大协议详解 一些假设 1 无限制的单工协议 乌托邦协议 五点假设 发送方 接收方 接受方 2 单工停 等协议 3 有噪声信道的单工协议 本文图片截取自 学堂在线 华南理工大学的计算机网络课程 一些假设 物理层 数据链路层和网络层
  • 视频格式无损/快速转换——ffmpeg(mkv等转mp4)

    非商业用途转载请务必注明出处 https blog csdn net qq 40491305 article details 103272651 最近用PR发现不支持mkv格式 需要转化为mp4 考虑到快速 无损以及我仅仅需要转码 懒得使用
  • java.lang.ArrayIndexOutOfBoundsException(数组越界)处理方法

    转发自https blog csdn net qq 34646449 article details 76146659 当你使用不合法的索引访问数组时会报数组越界这种错误 数组arr的合法错误范围是 0 arr length 1 当你访问这
  • 使用反射动态校验后台配置某字段是否允许为空

    背景 使用easyExcel读取数据 title不固定 后台可以配置title必填项 title顺序可改变 用户可以自定义title 不存储自定义信息即可 不报错 思路 不能使用easyExcel使用index的方式读取数据 改成value
  • 文件在使用FileChannel.map后不能被删除(Windows上)

    同事发现在Windows上使用FileChannel的map方法之后 不能够删除掉文件 我在Linux上试了一下 发现没这个问题 做个笔记 记录一下 import java io File import java io RandomAcce