结论:fileChannel在调用read方法时会先对position和limit的值进行检查,如果limit与position的值相等或者position大于limit则直接返回0,不会再调用操作系统的read方法了。
我们可以查看FileChannel抽象类的实现类FileChannelImpl中read(ByteBuffer byteBuffer)的源码:
/* */ public int read(ByteBuffer paramByteBuffer) throws IOException
/* */ {
/* 136 */ ensureOpen();
/* 中间的代码为判断文件是否打开,没有打开则执行对应的代码,其实不用看,因为ensureOpen()就已经在判断文件是否打开,没有则抛出异常,这可能
是为了在多线程的情况下出现的异常才做的第二次判断 */
/* */ do
/* */ {
//IOUtil.read将会从这个文件中读出数据进入buffer中,并返回一个状态码,不等于-3则退出循环
/* 149 */ i = IOUtil.read(this.fd, paramByteBuffer, -1L, this.nd);
/* 150 */ } while ((i == -3) && (isOpen()));
/* 151 */ int k = IOStatus.normalize(i);//当传入的值为0时,最终也会返回0
/* 153 */ this.threads.remove(j);
/* 154 */ IoTrace.fileReadEnd(localObject1, i > 0 ? i : 0L);
/* 155 */ end(i > 0);
//返回状态信息
/* 156 */ assert (IOStatus.check(i));return k;
/* */ }
/* */ finally
/* */ {
/* 省略...*/
/* */ }
/* */ }
/* */ }
我们查看IOUtil.read的源码
/* */ static int read(FileDescriptor paramFileDescriptor, ByteBuffer paramByteBuffer, long paramLong, NativeDispatcher paramNativeDispatcher)
/* */ throws IOException
/* */ {
/* 这里是针对buffer进行只读或者是直接缓冲区的判断*/
/* */
/* 195 */ ByteBuffer localByteBuffer = Util.getTemporaryDirectBuffer(paramByteBuffer.remaining());
/* */ try {
//调用本类的readIntoNativeBuffer方法,并将其返回值进行返回
/* 197 */ int i = readIntoNativeBuffer(paramFileDescriptor, localByteBuffer, paramLong, paramNativeDispatcher);
/* 198 */ localByteBuffer.flip();
/* 199 */ if (i > 0)
/* 200 */ paramByteBuffer.put(localByteBuffer);
/* 201 */ return i;
/* */ } finally {
/* 203 */ Util.offerFirstTemporaryDirectBuffer(localByteBuffer);
/* */ }
/* */ }
查看readIntoNativeBuffer方法的源码
/* */ private static int readIntoNativeBuffer(FileDescriptor paramFileDescriptor, ByteBuffer paramByteBuffer, long paramLong, NativeDispatcher paramNativeDispatcher)
/* */ throws IOException
/* */ {
//获得当前buffer的position值
/* 211 */ int i = paramByteBuffer.position();
//获取当前buffer的limit值
/* 212 */ int j = paramByteBuffer.limit();
/* 213 */ assert (i <= j);
当buffer的position值和limit值相等时,k的值就会是0,
/* 214 */ int k = i <= j ? j - i : 0;
/* */ //k等于0,则返回0
/* 216 */ if (k == 0)
/* 217 */ return 0;
/* 218 */ int m = 0;
/* 219 */ if (paramLong != -1L) {
/* 220 */ m = paramNativeDispatcher.pread(paramFileDescriptor, ((DirectBuffer)paramByteBuffer).address() + i, k, paramLong);
/* */ }
/* */ else {
/* 223 */ m = paramNativeDispatcher.read(paramFileDescriptor, ((DirectBuffer)paramByteBuffer).address() + i, k);
/* */ }
/* 225 */ if (m > 0)
/* 226 */ paramByteBuffer.position(i + m);
/* 227 */ return m;
/* */ }