Java 文件通道从';发言人的评论及解释

Java 文件通道从';发言人的评论及解释,java,nio,filechannel,Java,Nio,Filechannel,我已经阅读了FileChannel的transferFrom * <p> This method is potentially much more efficient than a simple loop * that reads from the source channel and writes to this channel. Many * operating systems can transfer bytes directly from the source cha

我已经阅读了
FileChannel
transferFrom

 * <p> This method is potentially much more efficient than a simple loop
 * that reads from the source channel and writes to this channel.  Many
 * operating systems can transfer bytes directly from the source channel
 * into the filesystem cache without actually copying them.  </p>

如果我从一个通道读取数据,然后将其写入另一个通道,它是否会将字节传输到缓存中?

是的,如果使用循环并从源通道读取字节缓冲区,然后将字节缓冲区写入文件通道,那么在写入结束时,字节/数据将位于文件系统缓存中。它们还将被复制到Java ByteBuffer中,这可能是从内核复制到应用程序内存(或“C堆”),然后复制到JVM堆(在最坏的情况下)

如果源通道是兼容的,那么操作系统可能能够避免复制到JVM堆中,甚至可能完全从内核中复制出来,而是直接从源文件页复制到目标文件页

如果您将看到性能上的任何真正改进,那么它将高度依赖于JVM版本、操作系统和文件系统。我不希望它的性能比Java编码的循环更差


Rob.

我试过,如果我使用一个非常大的
字节缓冲
,它将比
转移到
更快,这正常吗?我不太理解你的
到应用程序内存
,JVM不是直接操作主存吗?这与我过去的发现是一致的。过去是几年前的事了。对于我当时正在构建的应用程序,分配大型缓冲区是不可行的,因此我使用了中等大小的缓冲区(我认为是8K),并且跨平台的性能是相同的。只有在一个JVM/OS/文件系统组合中(记不清是哪个组合),它比transferFrom/To更糟糕。决定因素是我有机会使用读/写循环提供有关复制进度的信息。1) 分配Java对象和垃圾收集器的Java堆是最高的。2) 在C堆中,底层C结构被分配并直接指向ByteBuffers。如果在最坏的情况下从文件通道读取,可能会从内核页面复制到C缓冲区,然后复制到Java字节[]。这对我来说没有意义,如果JNI(C代码)将其读取到内存中,就不需要再次将其读取到Java堆中,我认为JNI直接使用Java堆。
Many operating systems can transfer bytes directly from the source channel
into the filesystem cache without actually copying them.