FileInputStream真的没有缓冲吗



FileInputStream使用此本机方法读取用户提供的缓冲区中的字节。正如我们在实现中看到的那样,用户空间缓冲区确实分配了长度为max(BUF_SIZE, supplied buffer length)的缓冲区。然后将该缓冲区传递给CCD_ 3。我无法找到这个方法的实现,但我很确定这是标准的C缓冲读取。为什么说FileInputStream没有缓冲?BufferedReader使用了什么额外的缓冲?

编辑:比较100M文件读取时间的基准及其结果:

Benchmark                         Mode  Cnt      Score      Error  Units
StreamIOBenchmark.bisMultiBytes   avgt   30     27.640 ±    1.117  ms/op
StreamIOBenchmark.bisSingleBytes  avgt   30    400.552 ±   26.921  ms/op
StreamIOBenchmark.fisMultiBytes   avgt   30     25.231 ±    1.459  ms/op
StreamIOBenchmark.fisSingleBytes  avgt   30  97991.213 ± 5620.685  ms/op

真正的区别是在读取单个字节时,因为FIS将为每个字节进行新的系统调用。然而,当一次读取8k字节时,FIS(fisMultiBytes)和BIS(bisMultiBytes)的性能非常相似。

FileInputStream真的没有缓冲吗?

是。真正地

我无法找到这个方法的实现,但我很确定这是标准的C缓冲读取。

不是。本机代码不使用C缓冲I/O。它正在执行对临时缓冲区的read(2)调用。然后,它将数据从临时缓冲器复制到呼叫者提供的CCD_ 10。

在我正在查看的Java 11u代码中,临时缓冲区是一个较小的堆栈上缓冲区,或者是一个较大的本地堆缓冲区,在native调用期间为malloc'd和free'd。

OpenJDK Java 11u代码库中的相对路径名是./src/java.base/share/native/libjava/io_util.c。查找readBytes方法。(这是通过./src/java.base/share/native/libjava/FileInputStream.c中的本地入口点方法调用的)

io_utils.c中的IO_Read是一个别名为handleRead的宏,它封装了read(2)调用。

更新

我刚刚注意到您已经找到了指向io_util.c的Java 8u版本的链接。它的行为方式与我上面描述的11u代码相同。所以,也许你只是看错了你找到的C代码?


为什么说FileInputStream没有缓冲?

它是"据说是";因为它确实没有缓冲

BufferedReader使用了什么额外的缓冲?

您可以通过查看BufferedReader的(Java)源代码来了解这一点。


提示:与其对JVM本机代码实现的工作方式做出(错误的)假设,不如下载并阅读OpenJDK源代码。任何有足够磁盘空间(1.2GB)的人都可以下载。