Java下FileChannel的实现剖析

匿名 (未验证) 提交于 2019-12-02 21:53:52

openjdk\jdk\src\share\classes\sun\nio\ch\FileChannelImpl.java
先尝试sendfile,如操作系统不支持,对于信任的channel类型,调用mmap,否则走标准的read/write系统调用。windows系统是不支持sendfile的,所以windows下实际走的是mmap,性能较之read/write方式也要好很多。
从源码来看,只有源为FileChannel才支持transfer这种高效的复制方式,其他如SocketChannel都不支持transfer模式。当然,目的Channel没有这种限制。所以一般可以做FileChannel->FileChannel和FileChannel->SocketChannel的transfer。

public long transferTo(long position, long count,                            WritableByteChannel target)         throws IOException     {         ensureOpen();         if (!target.isOpen())             throw new ClosedChannelException();         if (!readable)             throw new NonReadableChannelException();         if (target instanceof FileChannelImpl &&             !((FileChannelImpl)target).writable)             throw new NonWritableChannelException();         if ((position < 0) || (count < 0))             throw new IllegalArgumentException();         long sz = size();         if (position > sz)             return 0;         int icount = (int)Math.min(count, Integer.MAX_VALUE);         if ((sz - position) < icount)             icount = (int)(sz - position);          long n;          // Attempt a direct transfer, if the kernel supports it         if ((n = transferToDirectly(position, icount, target)) >= 0)             return n;          // Attempt a mapped transfer, but only to trusted channel types         if ((n = transferToTrustedChannel(position, icount, target)) >= 0)             return n;          // Slow path for untrusted targets         return transferToArbitraryChannel(position, icount, target);     }

openjdk\jdk\src\solaris\native\sun\nio\ch\FileChannelImpl.c
linux是sendfile64(我的是64位的java版本):

JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,                                             jint srcFD,                                             jlong position, jlong count,                                             jint dstFD) { #if defined(__linux__)     off64_t offset = (off64_t)position;     jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count);     if (n < 0) {         if (errno == EAGAIN)             return IOS_UNAVAILABLE;         if ((errno == EINVAL) && ((ssize_t)count >= 0))             return IOS_UNSUPPORTED_CASE;         if (errno == EINTR) {             return IOS_INTERRUPTED;         }         JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");         return IOS_THROWN;     }     return n;     ......

openjdk\jdk\src\windows\native\sun\nio\ch\FileChannelImpl.c
windows是不支持的:

JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,                                             jint srcFD,                                             jlong position, jlong count,                                             jint dstFD) {     return IOS_UNSUPPORTED; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!