- 浏览: 246851 次
- 性别:
- 来自: 大连
最新评论
-
di1984HIT:
不错。不错~
JIMI、JAI和ImageIO的一些感想 -
houyi521:
...
给OSGi加入数字签名及认证特性的思考 -
dsjt:
map是映射到直接内存,回收比较复杂。用堆内存缓存:<p ...
慎用 MappedByteBuffer! -
faint2010:
PHP这个基础本身是非持久的,你却硬要做持久层,无异于霸王硬上 ...
用PHP做ORM效率那是相当的低啊! -
wuhoufeng:
orm带来开发上的方便 但是增加性能优化上难度 所以要配合缓存 ...
用PHP做ORM效率那是相当的低啊!
<script type="text/javascript"><!----></script>
最近使用MD5进行大文件验证,固使用NIO这种高效率的模式来进行文件映射:
FileInputStream in = new FileInputStream(file); FileChannel ch = in.getChannel(); MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); messageDigest.update(byteBuffer); String md5 = bufferToHex(messageDigest.digest()); ch.close(); in.close();
本来想如果文件md5与数据库存储的值不同就删掉该文件的,结果出现了文件无法删除的情况。
抛出的违例
java.io.FileNotFoundException: E:\hello.jar
(请求的操作无法在使用用户映射区域打开的文件上执行。)
后来经查,原来是当使用 FileChannel.map 方法时,MappedByteBuffer 已经在系统内占用了一个句柄,而使用 FileChannel.close 方法是无法释放这个句柄的,且FileChannel有没有提供类似 unmap 的方法,因此会出现无法删除文件的情况。
此问题一直让我很郁闷,后来到网上查询到两种方法...
第一种:
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; } });
此种方法需要JDK支持,我用的是JRE 1.6,提示没有 sun.misc.Cleaner 类,JDK包太大,项目又不让用。
第二种方法是显性设置byteBuffer为null,并调用GC,没什么实际意义。
实在没招了,又回来使用InputStream了...
FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream((int)file.length()); byte[] cache = new byte[1048576]; for(int i = in.read(cache);i != -1;i = in.read(cache)){ out.write(cache, 0, i); } in.close(); out.close(); messageDigest.update(out.toByteArray()); md5 = bufferToHex(messageDigest.digest());
不知道SUN为啥要搞这种半截子工程,大家有什么其他解决方法么?
评论
19 楼
dsjt
2013-05-29
map是映射到直接内存,回收比较复杂。
用堆内存缓存:
用堆内存缓存:
ByteBuffer buffer= ByteBuffer.allocate(1024*1024); FileChannel.read(buffer);
18 楼
sonic39
2009-02-21
小弟过来学习中
17 楼
d2lorder
2008-12-23
哈哈 我也遇到过
但是使用 第一种方法就可以搞定了
第二种方法 也用过,也可以实现
但是使用 第一种方法就可以搞定了
第二种方法 也用过,也可以实现
16 楼
AreYouOK?
2008-12-23
引用
我觉得mappedbytebuffer更适用于文件较小,但是有些字节需要反复读取得情况
大约是这样的,对于计算一个大文件的MD5来说,每个字节都只读取一次,映射到内存应该是不会快的。
对于特别小的文件,javadoc是这么说的:
引用
For most operating systems, mapping a file into memory is more expensive than reading or writing a few tens of kilobytes of data via the usual read and write methods. From the standpoint of performance it is generally only worth mapping relatively large files into memory.
也就是说,它建议把“大”文件做映射(实际上它说的也就是要读写几十K),但是我想也许这个映射的开销是一次性的,对于小文件以后反复读写就快了吧。
这个映射的特点是可以将超过(物理内存+虚拟内存)、超过JVM最大内存大小的文件部分装入内存。因此,所谓装入内存实际上是虚拟的,我们看到的就是一个大数组,读的时候,如果在内存里面,就从内存里面读,否则就要读文件。
由于映射是操作系统负责的,所以其很多行为都是不确定的,在javadoc里面就有很多这方面的描述。主要是写操作后,数据对其它程序的可见性。
另外还有一个问题,就是map的文件部分的大小也是有限制的。如下:
WinXP 32位 2G内存,2G虚拟内存,Map一个2G的文件,XmX=64M
map 0~500M OK
map 0~1G 内存溢出错误
循环,每次map1M,返回的buffer不释放,到达将近2G时内存溢出,也就是说,map的文件部分的总和也是有限制的
Linux 32位 2G内存,1G虚拟内存,Map一个3G多的文件,XmX=64M
map 0~3G IllegalArgumentException,map的长度不能超过Integer.MAX_VALUE,也就是不能超过2G
map 0~Integer.MAX_VALUE ok
循环,每次map1M,返回的buffer不释放,到达2G后(2G或者2G多一点?)时内存溢出
Linux 64位 2G内存,2G虚拟内存,Map一个5G的文件,XmX=64M
map 0~5G IllegalArgumentException,map的长度不能超过Integer.MAX_VALUE,也就是不能超过2G
map 0~Integer.MAX_VALUE ok
循环,每次map1M,返回的buffer不释放,没有发现限制
有意思的是,第三个参数的类型是long,但是却不允许超过Interger.MAX_VALUE,不知是在其它操作系统下可以,还是给将来留一点余地?
反正现在在Linux64下,是基本够用了。
15 楼
bloodrate
2008-12-23
猜想这样,FileInputStream 的 read 方法是通过与本地文件的通道中从文件读取数据,由于只能知道当前读取的内容,未读取的内容在硬盘中处于未知状态,所以FileInputStream没有length方法(刚学io的时候觉得很蹩脚),想读第2个字节必选先读第1个字节.而用内存地址映射将整个文件存储到内存中,一切都变成可控可操作的,但是内容中对象确实要交由jvm处理,这点java机制所致没办法,至于为什么占着本地文件引用不释放就不理解了,按说文件被加载道内存里后就与本地文件划清界限了..
我觉得mappedbytebuffer更适用于文件较小,但是有些字节需要反复读取得情况
我觉得mappedbytebuffer更适用于文件较小,但是有些字节需要反复读取得情况
14 楼
seen
2008-12-23
期待yywill出来解释。。。
13 楼
kusix
2008-12-22
一年前就碰到过这个问题,当时也是被恶心到了,SUN的一个BUG。
我是用的第一种方法解决的。
我是用的第一种方法解决的。
12 楼
AreYouOK?
2008-12-22
我也遇到这个问题,它还有其他一些很不确定的行为,例如:
不是这样的,看javadoc,不知道为什么有这么恶心的设计:
引用
On some systems, acquiring a mandatory lock on a region of a file prevents that region from being mapped into memory, and vice versa. Programs that combine locking and mapping should be prepared for this combination to fail.
引用
MappedByteBuffer是java平台共享内存的实现,把硬盘虚拟为内存,主要用于进程间共享数据,所以在进程没有退出前文件是不允许删除的。
不是这样的,看javadoc,不知道为什么有这么恶心的设计:
引用
A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.
11 楼
gqf2008
2008-12-22
MappedByteBuffer是java平台共享内存的实现,把硬盘虚拟为内存,主要用于进程间共享数据,所以在进程没有退出前文件是不允许删除的。
10 楼
yipsilon
2008-12-22
通过 codeutil 的代码修正了问题,感谢!!!!
除非SUN把这个给解决,不然再也不想用ByteBuffer这东西了,哎哎。
除非SUN把这个给解决,不然再也不想用ByteBuffer这东西了,哎哎。
9 楼
gembler
2008-12-21
这个东西,我狂抓了大半年了··为了删除文件,用后台线程去gc``(幸好该操作不频)
这种情况下看gc log的时候··会出冷汗
这种情况下看gc log的时候··会出冷汗
8 楼
sdh5724
2008-12-21
看错了啊, 确实不应该这么写的。LZ要分段做。
7 楼
codeutil
2008-12-21
不说MappedByteBuffer的问题,楼主你如此hash有点不妥,如果是22G的文件你的写法都得全读到内存才计算hash。
public static String getHash(String fileName, String hashType) throws Exception { InputStream fis; fis = new FileInputStream(fileName); byte[] buffer = new byte[1024]; MessageDigest md5 = MessageDigest.getInstance(hashType); int numRead = 0; while ((numRead = fis.read(buffer)) > 0) { md5.update(buffer, 0, numRead); } fis.close(); return toHexString(md5.digest()); }
对比:
FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream((int)file.length()); byte[] cache = new byte[1048576]; for(int i = in.read(cache);i != -1;i = in.read(cache)){ out.write(cache, 0, i); } in.close(); out.close(); messageDigest.update(out.toByteArray()); md5 = bufferToHex(messageDigest.digest());
6 楼
sdh5724
2008-12-21
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038
大家看看吵上天了, 老外也抓狂呢。
大家看看吵上天了, 老外也抓狂呢。
5 楼
sdh5724
2008-12-21
楼住, 你发现的问题是真的。 你是发现了SUN的一个很严重的设计问题。 我也不知道SUN什么时候会解决, 在mmap中, SUN这个老顽固, 认为Java的内存管理就应该是jvm干的事情, 因此, 在mmap使用上, Sun依然认为mmap是jvm应该管理的内存资源。 在很多设计者的眼里, mmap资源应该属于一种特殊的内存资源, 而且他还是属于一种特殊的文件资源, 他根本不能使用jvm的内存管理办法来管理这个资源。当前mmap对象被JVM创建(ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());)后, 如果想释放, 就要等到GC干活的时候。 这个是非常恶心的设计。
另外有人把io/nio就是看作阻塞, 非阻塞的关系, 或者是同步与异步处理是不对的。nio的原理更应该理解为操作系统对资源一个处理方式,通过内核事件来通知资源就绪的情况, 这个处理模式极大的提高了系统的高并发处理能力和CPU利用效率, 仅此而已。
到目前为止, 没有好的解决办法(除了HACKING)
另外有人把io/nio就是看作阻塞, 非阻塞的关系, 或者是同步与异步处理是不对的。nio的原理更应该理解为操作系统对资源一个处理方式,通过内核事件来通知资源就绪的情况, 这个处理模式极大的提高了系统的高并发处理能力和CPU利用效率, 仅此而已。
到目前为止, 没有好的解决办法(除了HACKING)
4 楼
yywill
2008-12-21
把sun的包复制出来
rt.jar
然后自己精简一下
rt.jar
然后自己精简一下
3 楼
yipsilon
2008-12-21
MappedByteBuffer的cleaner方法不是公开的,必须使用上述的那种手段进行调用,这样有个问题就是,我们无法控制客户使用的JVM,因为很多Application Server的JVM都不是SUN的,例如IBM或BEA,使用SUN所独有的内部类和方法会导致兼容性问题。
begin 和 end 这两个方法我在AbstractInterruptibleChannel类中看到都是protected的,无法在程序中调用。兄弟能详细解释一下么?
begin 和 end 这两个方法我在AbstractInterruptibleChannel类中看到都是protected的,无法在程序中调用。兄弟能详细解释一下么?
2 楼
yywill
2008-12-21
请用begin和end标记你的map操作,告诉jvm你的map什么时候结束
boolean completed = false;
try {
begin();
completed = ...; // Perform blocking I/O operation
return ...; // Return result
} finally {
end(completed);
}
boolean completed = false;
try {
begin();
completed = ...; // Perform blocking I/O operation
return ...; // Return result
} finally {
end(completed);
}
1 楼
yywill
2008-12-21
1.MappedByteBuffer 也有clean方法啊。不行么。
2.NIO出现这种错误是正常的,因为NIO的含义是non-blocking IO。所以关闭的方法和IO中的操作不一样。你始终要处理异步或者是多线程的问题。
请自己查看:
java.nio.channels.spi.AbstractInterruptibleChannel
J2SE没有半截子工程。不要用IO的方法来操作NIO的类,当你用到NIO就要始终处理多线程,处理异步。
2.NIO出现这种错误是正常的,因为NIO的含义是non-blocking IO。所以关闭的方法和IO中的操作不一样。你始终要处理异步或者是多线程的问题。
请自己查看:
java.nio.channels.spi.AbstractInterruptibleChannel
J2SE没有半截子工程。不要用IO的方法来操作NIO的类,当你用到NIO就要始终处理多线程,处理异步。
发表评论
-
在64位Ubuntu下安装Flash Media Server 3.5
2010-06-10 08:43 2302众所周知,Flash Media Server 是32位的程序 ... -
安装 ESXi 4 ?请先弄个带缓存的SCSI卡吧。
2010-06-01 17:45 1283最近为安装Oracle买了一个测试服务器,主板内置SCSI芯片 ... -
iPad的宣传广告真是搞笑啊!!!
2010-01-29 00:34 1887不知道他们的中国设计师是怎么想的,QQ这种大部分时间是后台运行 ... -
新版JRE内置新的LAF:Nimbus,太漂亮了!
2010-01-26 18:31 3264从6u10开始内置到JRE中了,可以在UIManager中通过 ... -
Michael Widenius 为什么要拯救MySQL?
2010-01-21 11:22 1833最近,呼吁中国人民签名以拯救MySQL的新闻挺多啊 ... -
PHP会倒掉吗?
2009-11-24 12:39 5429最近有不少文章讨论PHP如何如何不好,如何如何不适应企业应用, ... -
"脑子有Bing" 不知道是夸赞还是贬低...
2009-08-04 00:45 1291个人感觉微软有时候很搞笑,经常搞出比较可爱的广告啊、产品名字啊 ... -
iPhone Development Program 好像不支持国内注册了
2009-07-18 15:17 2664这几天研究iDP的注册流程,申请了好多Apple ID都无法登 ... -
谷歌被地产商山寨了~~
2009-06-29 15:18 948今天出去吃饭,突然看到“谷歌”字样,还以为Google到大连来 ... -
看看我们数据处理部门的杰作吧!
2009-02-22 01:03 1322这套系统叫做 DMP,全称 Data Management P ... -
传说中的Java动态注释?
2008-10-18 02:01 1768动态注释是一个有用的功能。它可以使用多行的字符串来指定在行中测 ... -
要不我给你猪
2008-10-16 23:31 1002男赶集卖猪,天黑遇雨,二十头猪未卖成,到一农家借宿。 少 ... -
没事做了个3D模型,纯Flash的。
2008-10-16 23:08 1385wsad 是前后左右行走,↑↓←→ 是视角前后左右移动,带碰撞 ... -
Godaddy 网站挂了....
2008-10-14 02:41 1023本来想去管理一下服务器,结果没想到这么大的网站也挂了,还挂了这 ... -
Linkin Park演唱会取消了...
2008-10-08 03:13 1092因小C的背伤取消了,两个字:不爽! 听不到现场原唱,看来只 ... -
JIMI、JAI和ImageIO的一些感想
2008-09-05 03:52 7673最近研究个项目,涉及到多页TIFF分页保存问题。于是就研究呀研 ... -
使用iPhone发文章测试
2008-03-04 23:39 1057本文使用iPhone发表! 使用了iPhone也有一段时间 ... -
已将手机升级到砖头级!
2008-01-31 19:50 1208今儿备用电池终于到了,谢天谢地。此电池电量是2200毫安时,配 ... -
成功滴将iPhone升级到1.1.3版本!
2008-01-26 19:47 1403升级用了10分钟左右,在 Mac OSX 10.5 上搞的,汉 ... -
iphone超级强悍的功能!
2008-01-22 23:50 1121在Installer.app的package包里,竟然看到了a ...
相关推荐
《深入浅出MappedByteBuffer》这篇文章主要探讨了Java NIO中MappedByteBuffer这一高效处理大文件的机制,以及与其相关的计算机内存管理概念。首先,我们来详细理解一下这些知识点。 内存管理是计算机系统的重要组成...
Bug ID 4724038 (fs) Add unmap method to MappedByteBuffer
本人初学c++,写了一个小软件,能把大文件分割问小文件,然后可以统国网络传输,到了网络另一端,再用此软件拼接! 希望用过的人能提宝贵意见! 13521825644 qq 362192302
Java中的MappedByteBuffer是Java NIO(New Input/Output)库的一部分,它提供了一种高效的方式来访问和操作大文件。在标题和描述中提到的“文件内存映射缓冲区”是Java处理大文件的一种高级技术,它允许将文件直接...
在Java中,可以通过`java.nio.MappedByteBuffer`类来实现共享内存功能,这被称为内存映射文件(Memory-Mapped File,MMF)。 `MappedByteBuffer`是NIO中的一种特殊缓冲区,它将文件的一部分映射到内存中,使得文件...
(用于TCP网络编程,客户端和服务器端都能用) ServerSocketChannel (用于TCP网络编程,专用与服务器端) 常见的Buffer,用来缓冲读写数据。 ByteBuffer MappedByteBuffer DirectByteBuffer HeapByteBuffer ...
为了有效地读取大文件,可以使用缓冲区(Buffer)和内存映射文件(MappedByteBuffer)技术。下面将详细解释如何使用这些技术以及代码中的关键部分。 1. **缓冲区(Buffer)**: Java中的缓冲区是用于提高数据读写...
例如,可以将数据按每10万条或更少的数量进行分组,然后用多线程并行处理这些数据块。多线程可以有效利用多核CPU的计算能力,提高整体导出效率。 多线程编程在Java中可以通过ExecutorService和Future来实现。创建一...
对于需要随机访问或文件特别大的情况,推荐使用`RandomAccessFile`和`FileChannel`的组合,特别是利用`MappedByteBuffer`进行内存映射文件读取。这种方式能够显著提高文件的读取速度,因为数据直接从磁盘映射到内存...
在Java NIO中,内存映射文件(MappedByteBuffer)是一个重要的特性,它允许将文件直接映射到内存中,以便于快速访问和修改文件内容。这一特性不仅提高了读写效率,而且还能用于进程间通信(IPC)。 内存映射文件的...
在IT行业中,文件数据的处理是一项常见的任务,特别是在数据交换和存储时。"读取文件数据并解析成bean实体类"这一主题涉及到的核心知识点主要包括文件操作、数据解析以及对象映射。下面将详细阐述这些概念及其应用。...
本主题聚焦于Java平台下如何实现高效的文件操作,特别是利用内存映射(MappedByteBuffer)进行读写和通过网络进行文件传输。以下是相关的知识点详解: 1. **内存映射文件(MappedByteBuffer)**: 内存映射文件是...
另外,虽然 MappedByteBuffer 在逻辑上应该是 DirectByteBuffer 的子类,而且 MappedByteBuffer 的内存的 GC 和直接内存的 GC 类似(和堆 GC 不同),但是分配的 MappedByteBuffer 的大小不受 -XX:...
函数原型 private MappedByteBuffer mappedFile2Buffer(File f) throws Exception 函数说明 把日志文件映射成内存缓冲 参数说明 @param File f日志文件 返回说明 @return MappedByteBuffer 内存映射缓冲。 异常说明 ...
- **MappedByteBuffer**:文件映射缓冲区,它允许将文件的一部分直接映射到内存,从而提供快速的文件访问。 2. **按行读取的实现**: - 类`NioReader`初始化时,创建了一个`FileInputStream`和`FileChannel`对象...
MappedByteBuffer buffer = remoteChannel.map(FileChannel.MapMode.READ_ONLY, remoteChannel.position(), blockSize); if (buffer.limit() == 0) break; localChannel.write(buffer); } // 关闭文件通道 ...
FileChannel提供了map()方法,可以将文件的一部分或全部映射到Java虚拟机的内存中,形成一个MappedByteBuffer对象。这样,对MappedByteBuffer的操作实际上就是对文件的直接操作,无需频繁地进行磁盘I/O,大大提高了...
MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, 0, fileChannel.size()); CharBuffer charBuffer = Charset.forName("UTF-8").decode(mappedByteBuffer); System.out.println...
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } channel.close(); ``` 这段代码将...
在Java语言中,我们可以使用RandomAccessFile和MappedByteBuffer类来读取QQwry.dat文件,并通过IPSeeker类来实现IP定位的功能。IPSeeker类中,我们可以使用Hashtable来存储国家和区域的信息,并使用ArrayList来存储...