为啥 FileChannel.map 占用了 Integer.MAX_VALUE 的数据?
Posted
技术标签:
【中文标题】为啥 FileChannel.map 占用了 Integer.MAX_VALUE 的数据?【英文标题】:Why does FileChannel.map take up to Integer.MAX_VALUE of data?为什么 FileChannel.map 占用了 Integer.MAX_VALUE 的数据? 【发布时间】:2011-12-25 23:06:55 【问题描述】:使用 FileChannel.map 时出现以下异常
Exception in thread "main" java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE
at sun.nio.ch.FileChannelImpl.map(Unknown Source)
at niotest.NioTest.readUsingNio(NioTest.java:38)
at niotest.NioTest.main(NioTest.java:64)
快速查看 OpenJdk 实现表明 FileChannelImpl
中的方法 map(..) 将 long
类型的 size
作为输入。但在正文中,它将它与Integer.MAX_VALUE
进行比较,如果大于则抛出错误。为什么将long
大小作为输入,但将其限制为最大integer
长度?
有人知道这个实现背后的具体原因吗? 还是某种错误?
来源网址 - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/nio/ch/FileChannelImpl.java
我在 64 位 Windows-2k8 上使用 64 位 JRE 运行此程序
【问题讨论】:
【参考方案1】:这不是特定于实现的错误。大小是在FileChannel.map 中定义的一样长,但是...
size - 要映射的区域的大小;必须为非负且不大于 Integer.MAX_VALUE
所有兼容的 JVM 实现都将采用这种方式。我怀疑原因是历史(谁需要访问大于 2GB 的文件?;)和试图在 Java 的更高版本中推动事情的结合(允许大于 Integer.MAX
的值比它更容易将数据类型从int
更改为long
。)
很多人在 Java API 中发现这种基于 int 的思想对于任何文件都非常混乱和短视。但请记住,Java 于 1995 年开始开发!我敢肯定 2GB 在当时似乎是一个相对安全的值。
【讨论】:
真正的原因是 ByteBuffer.capacity 仅限于 int 的范围,NIO 是 1.4 进来的,所以没有像 '95 @bestsss:他们选择了int
而不是long
,这在当时是不够的。 long
从第 0 天开始就使用 Java。(在 32 位机器上,使用 64 位数字会昂贵。)和“是”,Java 1.4 于 2002 年 2 月发布,但 NIO 起源于 JSR 51,于 2000 年 1 月正式启动。(2000 年平均销售的 HDD 大小为 10GB?20GB?) JSR 51 的最初起源是在那之前几个聪明的工程师之间的一品脱啤酒。肯定不会迟于 1999 年底。
我对 HDD 的记忆是 80GB,java 一直瞄准 solaris big iron。 File.length()
自 Java 诞生以来一直是 long
。选择int
与 CPU 中的内部优化和分支预测有关。例如,for(long i=....)
从未优化或展开...并且您希望 ByteBuffer 上的循环既消除范围检查又展开。
我说的是“平均”,而不是“最大”。 en.wikipedia.org/wiki/File:Hard_drive_capacity_over_time.svg (令人惊讶的是,这些数字看起来如此之小。我从千字节时代开始就一直在购买存储空间......这太棒了。) 我认为我的观点是:int
over long
因为时间是有意义的。欢迎您在 1995 年与 1999 年分道扬镳,但这并不夸张。
哦,那时的 Java 也瞄准了“一次编写,随处运行......包括 GUI 的东西”......不仅仅是沉重的 Sun 工具包。【参考方案2】:
ByteBuffer 的容量被限制为 Integer.MAX_VALUE,所以没有办法映射比它更大的东西。
看:MappedByteBuffer map(MapMode mode, long position, long size)
position
必须很长,原因很明显。size
不需要很长,但在任何计算中都必须提升它 - 例如位置+大小必须是正多头。操作系统映射确实可以使用long
来承载映射,map
函数 (mmap) 可能需要映射超过 Integer.MAX_VALUE 以保留页面大小,但 ByteBuffer 不能使用它。
总体上int
在java的设计中很深,没有size_t
类似的C类型,大量使用long
而不是int会降低性能。所以最后:如果您需要大于 2GB 的地图,只需使用多个 ByteBuffer。
【讨论】:
以上是关于为啥 FileChannel.map 占用了 Integer.MAX_VALUE 的数据?的主要内容,如果未能解决你的问题,请参考以下文章
windows服务器为啥我的新版的phpstudy8.0自带的ftp报530 user cannot log in?