MappedByteBuffer的映射内存的释放
来源:互联网 发布:qq ubuntu 安装包下载 编辑:程序博客网 时间:2024/06/06 01:09
MappedByteBuffer的内存释放,主要由垃圾回收引起的。
首先,来看一下Oracle的bug list,这是一个无法修复的bug,所以在使用MappedByteBuffer的时候一定要注意内存的释放。
第一个case是:
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;public class FileDelete {public static void main(String[] args) {FileInputStream fis = null;File f = new File("a.txt");try {fis = new FileInputStream(f);FileChannel fc = fis.getChannel();// 把文件映射到内存MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,(int) fc.size());// TODOfc.close();fis.close();} catch (FileNotFoundException ex) {System.err.println("Error! " + ex.getMessage());System.exit(2);} catch (IOException e) {System.err.println("Error! " + e.getMessage());System.exit(3);}// 删除文件boolean deleted = f.delete();if (!(deleted)) {System.err.println("Could not delete file " + f.getName());}}}删除文件失败!原因是没有释放内存。
第二个case是:
import java.io.File;import java.io.RandomAccessFile;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;public class TestMemoryMapping {public static void main(String[] args) {try {File f = File.createTempFile("Test", null);f.deleteOnExit();RandomAccessFile raf = new RandomAccessFile(f, "rw");raf.setLength(1024);FileChannel channel = raf.getChannel();MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);channel.close();raf.close(); buffer = null;// System.gc();if (f.delete())System.out.println("Temporary file deleted: " + f);elseSystem.err.println("Not yet deleted: " + f);} catch (Exception ex) {ex.printStackTrace();}}}将buffer引用设为null,还是失败。我们都知道,垃圾回收器不保证立即回收垃圾,是不可靠的。添加注释掉的代码
System.gc();会显示的进行垃圾回收,但是同样地,这是没法保证的。我在本机上运行了10000次,失败了五六次。
究其原因,FileChannel在调用了map方法,进行内存映射得到MappedByteBuffer,但是没有提供unmap方法(),释放内存。事实上,unmap方法是在FileChannelImpl类里实现的,是个私有方法。在finalize延迟的时候,unmap方法无法调用,在删除文件的时候就会因为内存未释放而失败。不过可以通过显示的调用unmap方法来释放内存。
import java.io.File;import java.io.RandomAccessFile;import java.lang.reflect.Method;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import sun.nio.ch.FileChannelImpl;public class TestMemoryMapping {public static void main(String[] args) {try {File f = File.createTempFile("Test", null);f.deleteOnExit();RandomAccessFile raf = new RandomAccessFile(f, "rw");raf.setLength(1024);FileChannel channel = raf.getChannel();MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);channel.close();raf.close();// 加上这几行代码,手动unmapMethod m = FileChannelImpl.class.getDeclaredMethod("unmap",MappedByteBuffer.class);m.setAccessible(true);m.invoke(FileChannelImpl.class, buffer);if (f.delete())System.out.println("Temporary file deleted: " + f);elseSystem.err.println("Not yet deleted: " + f);} catch (Exception ex) {ex.printStackTrace();}}}则可以保证,成功释放内存
在别的地方也找到类似的处理方法,不过是让buffer本身来释放内存
AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]); getCleanerMethod.setAccessible(true); sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(byteBuffer, new Object[0]); cleaner.clean(); } catch (Exception e) { e.printStackTrace(); } return null; }});其实两种方法都是了Cleaner类的,clean方法。
我们从FileChannelImpl的unmap方法来入手
private static void unmap(MappedByteBuffer bb) { Cleaner cl = ((DirectBuffer)bb).cleaner(); if (cl != null) cl.clean(); }这是一个私有方法,调用了Cleaner的clean方法来释放内存,所以我们也可以直接在代码里使用以上代码来释放内存。
0 0
- MappedByteBuffer的映射内存的释放
- 内存映射文件:MappedByteBuffer
- java内存映射类MappedByteBuffer
- Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer
- 使用MappedByteBuffer读取大文件(1G以上)和释放MappedByteBuffer的资源
- 释放.NET Big Memory和内存映射文件的能量
- MappedByteBuffer的Bug
- MappedByteBuffer的使用
- MappedByteBuffer的使用
- MappedByteBuffer的使用
- MappedByteBuffer的使用
- MappedByteBuffer的使用
- MappedByteBuffer的学习
- 体会内存的释放
- 内存申请的释放
- Vector的内存释放
- vector的内存释放
- vector的内存释放
- 关于coredump文件
- Vim批量注释
- ios xcode6静态库.a文件的制作(兼容真机与模拟器)
- ndoutils(ndo2db)安装部署
- crontab使用说明
- MappedByteBuffer的映射内存的释放
- visual studio的/stack设置
- strcpy函数
- 在11gR2中可能惹祸的新特性
- 【Flume】flume ng 1.5.2源码编译的问题
- MD5加密算法
- iOS重绘机制drawRect
- Ten years of Taiyuan from the pollution first to best practices _ Shanxi news _ Shanxi News Network
- Storm Topology的生命周期过程分析