论坛首页 Java企业应用论坛

慎用 MappedByteBuffer!

浏览 14616 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-22  
通过 codeutil 的代码修正了问题,感谢!!!!

除非SUN把这个给解决,不然再也不想用ByteBuffer这东西了,哎哎。
0 请登录后投票
   发表时间:2008-12-22  
MappedByteBuffer是java平台共享内存的实现,把硬盘虚拟为内存,主要用于进程间共享数据,所以在进程没有退出前文件是不允许删除的。
0 请登录后投票
   发表时间:2008-12-22  
我也遇到这个问题,它还有其他一些很不确定的行为,例如:
引用
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.
0 请登录后投票
   发表时间:2008-12-22  
一年前就碰到过这个问题,当时也是被恶心到了,SUN的一个BUG。

我是用的第一种方法解决的。
0 请登录后投票
   发表时间:2008-12-23  
期待yywill出来解释。。。
0 请登录后投票
   发表时间:2008-12-23  
猜想这样,FileInputStream 的 read 方法是通过与本地文件的通道中从文件读取数据,由于只能知道当前读取的内容,未读取的内容在硬盘中处于未知状态,所以FileInputStream没有length方法(刚学io的时候觉得很蹩脚),想读第2个字节必选先读第1个字节.而用内存地址映射将整个文件存储到内存中,一切都变成可控可操作的,但是内容中对象确实要交由jvm处理,这点java机制所致没办法,至于为什么占着本地文件引用不释放就不理解了,按说文件被加载道内存里后就与本地文件划清界限了..

我觉得mappedbytebuffer更适用于文件较小,但是有些字节需要反复读取得情况
0 请登录后投票
   发表时间: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下,是基本够用了。




0 请登录后投票
   发表时间:2008-12-23  
哈哈  我也遇到过
但是使用 第一种方法就可以搞定了
第二种方法 也用过,也可以实现
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics