`
yonlist
  • 浏览: 82881 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

MappedByteBuffer 之文件删除问题

阅读更多

熟悉nio的朋友都知道,MappedByteBuffer大幅提高了IO效率,但却有个比较严重的问题。

看如下测试代码:

public class TestMappedByteBufferDeleteFile {
	
	File testFile;
	
	/**
	 * 创建测试文件
	 * @throws URISyntaxException 
	 * @throws IOException 
	 */
	@Before public void createFile() throws URISyntaxException, IOException {
		testFile = new File(this.getClass().getResource(".").getPath() + "/test.txt");
		if(!testFile.exists()) {
			testFile.createNewFile();
		}
		FileOutputStream fos = new FileOutputStream(testFile);
		fos.write("TestMappedByteBufferDeleteFile".getBytes());
		fos.close();
	}
	
	/**
	 * 测试使用MappedByteBuffer后直接删除文件
	 * @throws IOException 
	 */
	@Test public void testDeleteFile() throws IOException {
		map(testFile);
		testFile.delete();
		Assert.assertEquals(false, testFile.exists());
	}
	
	/**
	 * 映射文件,返回MappedByteBuffer
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public MappedByteBuffer map(File file) throws IOException {
		FileInputStream in = new FileInputStream(file);   
		FileChannel ch = in.getChannel();
		MappedByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
		ch.close();
		in.close();
		return buffer;
	}
}

 Junit运行,结果断言失败,文件没删除成功。

 

解决方法是加上如下代码:

/**
	 * 清理MappedByteBuffer句柄
	 * @param buffer
	 */
	public static void clean(final MappedByteBuffer buffer) {
		if (buffer == null) {
			return;
		}
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			
			public Object run() {
				try {
					Method getCleanerMethod = buffer.getClass().getMethod(
							"cleaner", new Class[0]);
					if (getCleanerMethod != null) {
						getCleanerMethod.setAccessible(true);
						Object cleaner = getCleanerMethod.invoke(buffer,
								new Object[0]);
						Method cleanMethod = cleaner.getClass().getMethod(
								"clean", new Class[0]);
						if (cleanMethod != null) {
							cleanMethod.invoke(cleaner, new Object[0]);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return null;
			}
}

 然后将testDeleteFile() 作如下修改:

/**
	 * 测试使用MappedByteBuffer后调用clean方法后删除文件
	 * @throws IOException 
	 */
	@Test public void testDeleteFile() throws IOException {
		MappedByteBuffer buffer = map(testFile);
		clean(buffer);
		testFile.delete();
		Assert.assertEquals(false, testFile.exists());
	}

 

再运行Junit,成功!

 

之所以出现这种情况,是因为文件句柄没有被清除,还被MappedByteBuffer占据,导致外部无法操作。而要清除,得等GC收集了。

 

不知Sun何时可以提供MappedByteBuffer的unmap!

另请关注该链接:http://bugs.sun.com/view_bug.do?bug_id=4724038

分享到:
评论
1 楼 dyllove98 2011-05-26  
Here is a workaround. It uses internal JVM API to call the cleaner instead of reflection. I know it is uggly, but as long as Java provides this for us this is what we have to do.  Should be safe in a single thread.

Any comments?

ByteBuffer buf = null;
try {
    buf = allocateByteBuffer();
    doWork(buf);
} finally {
    if (buf != null && buf.isDirect()) {
        ((sun.nio.ch.DirectBuffer) buf).cleaner().clean();
    }
}

相关推荐

    深入浅出MappedByteBuffer.pdf

    深入浅出MappedByteBuffer

    读取文件数据并解析成bean实体类

    很多时候需要文件做数据交互,接收到文件后需要对文件解析成bean实体类,这里提供的是工具类,任意文件转任意实体都可以,只要简单的配置一下Class类,很实用

    Bug ID 4724038 (fs) Add unmap method to MappedByteBuffer

    Bug ID 4724038 (fs) Add unmap method to MappedByteBuffer

    文件分割和合并(您的文件大的不能传输怎么办?)

    本人初学c++,写了一个小软件,能把大文件分割问小文件,然后可以统国网络传输,到了网络另一端,再用此软件拼接! 希望用过的人能提宝贵意见! 13521825644 qq 362192302

    j2se项目源码及介绍_last指令

    参数说明 MappedByteBuffer buffer 日志文件的内存缓冲 Vector&lt;LogRecord&gt; logins 日志的登入数据 Vector&lt;LogRecord&gt; logouts 日志的登出数据 返回说明 无 异常说明 @throws 考虑异常 流程原理 调用实例 函数原型...

    Android渠道打包工具packer-ng-plugin.zip

    }读取ZIP文件注释,有两个版本的实现,这里使用的是 RandomAccessFile ,另一个版本使用的是 MappedByteBuffer ,经过测试,对于特别长的注释,使用内存映射文件读取性能要稍微好一些,对于特别短的注释(比如渠道名...

    mmf4j:MemoryMappedFiles4Java

    与已经存在的MappedByteBuffer相比,目标是更好地控制创建,修改和销毁。 它试图统一在不同操作系统上使用此类映射的接口,这意味着许多细节无法实现。 此外,在某些情况下,您可能需要完成目标平台上可能不需要的...

    ip地址库 很全的库

    // 如果打开文件成功,读取文件头信息 if (ipFile != null) { try { ipBegin = readLong4(0); ipEnd = readLong4(4); if (ipBegin == -1 || ipEnd == -1) { ipFile.close(); ...

    【密码:5261】Oracle官网下载64位-JDK14

    jdk14新特性:改进NullPointerExceptions,通过准确描述哪些变量为null...非易失性映射的字节缓冲将添加新的JDK特定文件映射模式,该模式允许FileChannel API用于创建引用非易失性内存(NVM)的MappedByteBuffer实例。

    mmfinvoker:简单的进程间 java 请求-响应库

    mmfinvoker 这是一个简单的 java 库,它使用 nio.MappedByteBuffer 在内存映射文件上实现请求/响应功能。

    百度地图开发java源码-inertiaSearch:挑战赛

    百度地图开发java源码 tmp #inertiaSearch 2016年写的代码,现在觉得思路有很多提升的地方,但是毕竟...项目大量的使用了nio中的mmap(MappedByteBuffer) 对于原始的数据文件做内存映射,并做对应索引,所有索引做hash

    commons-mmf.rar_java nio_java共享内存_共享内存

    java的共享内存管理.基于MMF设计。封装了java.nio.MappedByteBuffer.在大流量实时业务系统时,可以极大的提高处理效率

    txt文档阅读器

    //MappedByteBuffer 将文件直接映射到内存 private int m_mbBufLen = 0; private int m_mbBufBegin = 0; private int m_mbBufEnd = 0; private String m_strCharsetName = "gbk";//文本格式 private Bitmap m_...

    jdk-14_linux-x64_bin.rpm

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

    Android代码-BitMap

    a pratise of bigdata sorting,use some common util or class,like File,FileOutputStream,RandomAccessFile,HashMap,BufferedOutputStream,ByteBuffer,MappedByteBuffer,FileInputStream. as a newer of ...

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

    SAMBox使用允许使用基于java.nio.channels.FileChannel , java.io.InputStream和java.nio.MappedByteBuffer的提供的实现之一(是否缓冲)。 通过使用java.lang.StringBuilder池最小化GC。 通过绑定视图的概念直接...

    CsvReader:CsvReader

    the performance improvement is not so much as against using MappedByteBuffer. -&gt; Otherwise I will totally use MappedByteBuffer 我无法在symbol.txt上进行验证。 单元测试:我找不到足够的时间来运行所有...

    javaredis源码-jredis-master:java实现redis

    java redis源码杰里迪斯 Java的redis实现,与redis服务器相同。 特征 ...MappedByteBuffer 2.fixed unit size ,head 4 byte write in last item position, and then each item write in 4 byte with i

    java8源码-netty-learn:这是一个用于netty学习的工程

    MappedByteBuffer DirectByteBuffer HeapByteBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer CharBuffer Selector选择器 Selector的作用就是配合一个线程来管理多个channel,获取这些channel上...

Global site tag (gtag.js) - Google Analytics