为什么 FileChannel.map 最多需要 Integer.MAX_VALUE 的数据?

2022-09-03 07:38:25

我在使用 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 实现表明,中的方法 map(..) 采用类型作为输入。但是在身体内部,它会将其与之进行比较,如果它大于此,则会引发错误。为什么将大小作为输入,但将其限制为最大长度?FileChannelImplsizelongInteger.MAX_VALUElonginteger

有谁知道这个实现背后的具体原因?还是某种错误?

源网址 - 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 中被定义为 long,但是...

size - 要映射的区域的大小;必须为非负数且不大于整数.MAX_VALUE

所有兼容的 JVM 实现都将如此。我怀疑原因是历史记录的组合(谁需要访问大于2GB的文件?;)并试图在更高版本的Java中推动事情向前发展(允许大于将数据类型从更改为的值更容易。Integer.MAXintlong

很多人发现Java API中关于任何File的这种基于int的想法非常令人困惑和短视。但请记住,Java在1995年开始开发!我敢肯定,2GB在当时似乎是一个相对安全的价值。


答案 2

ByteBuffer 的容量限制为 Integer.MAX_VALUE,因此无法映射任何大于该值的内容。

看:
由于明显的原因,必须做多。
不需要做多,但在任何计算中都必须提升它 - 例如,位置+大小必须是正多头。操作系统映射确实可以用来承载映射,函数(mmap)可能需要映射更多的整数.MAX_VALUE,以保持页面大小,但ByteBuffer不能使用它。MappedByteBuffer map(MapMode mode, long position, long size)positionsizelongmap

总的来说,Java的设计非常深入,并且没有类似C的类型,大规模使用而不是int会降低性能。所以最后:如果你需要比2GB更大的地图,只需使用多个ByteBuffer。intsize_tlong


推荐