上文已經說了FileChannel是一個抽象類,FileChannelImpl是其實現,接下來介紹FileChannelImpl,參考代碼來自OpenJDK7
首先
public class FileChannelImpl extends FileChannel
該類的成員有:
// Memory allocation size for mapping buffers
private static final long allocationGranularity;
// Used to make native read and write calls
private final FileDispatcher nd;
// File descriptor
private final FileDescriptor fd;
// File access mode (immutable)
private final boolean writable;
private final boolean readable;
private final boolean append;
// Required to prevent finalization of creating stream (immutable)
private final Object parent;
// Thread-safe set of IDs of native threads, for signalling
private final NativeThreadSet threads = new NativeThreadSet(2);
// Lock for operations involving position and size
private final Object positionLock = new Object();
//發現NIO這些類里面好多直接拿一個Object當做鎖用的,沒有用ReentrantLock等顯式鎖,畢竟1.6之后內置鎖的效率已經得到了提升,並且更方便
關於FileDescriptor的描述:
Instances of the file descriptor class serve as an opaque handle to the underlying machine-specific structure representing an open file, an open socket, or another source or sink of bytes. The main practical use for a file descriptor is to create a FileInputStream
or FileOutputStream
to contain it.
Applications should not create their own file descriptors.
接下來介紹私有構造函數
private FileChannelImpl(FileDescriptor fd, boolean readable,
boolean writable, boolean append, Object parent)
{
this.fd = fd;
this.readable = readable;
this.writable = writable;
this.append = append;
this.parent = parent;
this.nd = new FileDispatcherImpl(append);
}
既然是私有的那么我們只能使用Open來獲取一個實例,關於參數總的parent 我認為是這個FileChannel對應的FileInputStream之類。
// Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
public static FileChannel open(FileDescriptor fd,
boolean readable, boolean writable,
Object parent)
{
return new FileChannelImpl(fd, readable, writable, false, parent);
}
// Used by FileOutputStream.getChannel
public static FileChannel open(FileDescriptor fd,
boolean readable, boolean writable,
boolean append, Object parent)
{
return new FileChannelImpl(fd, readable, writable, append, parent);
}
接下來將介紹FileChannel的close 、read 和write position方法
先說close方法是AbstractInterruptibleChannel中定義的方法。一下是關於該類的簡單信息
public abstract class AbstractInterruptibleChannel
implements Channel, InterruptibleChannel
該類中close的定義:
public final void close() throws IOException {
synchronized (closeLock) {
if (!open)
return;
open = false;
implCloseChannel();
}
}
先說closeLock, 聲明為一個final 類成員 private final Object closeLock = new Object();
再說implCloseChannel() protected abstract void implCloseChannel() throws IOException;顯而易見繼承該抽象類的類來實現該抽象方法
FileChannelImpl的implCloseChannel() 方法
protected void implCloseChannel() throws IOException {
// Release and invalidate any locks that we still hold
if (fileLockTable != null) {
for (FileLock fl: fileLockTable.removeAll()) {
synchronized (fl) {
if (fl.isValid()) {
nd.release(fd, fl.position(), fl.size());
((FileLockImpl)fl).invalidate();
}
}
}
}
nd.preClose(fd);
threads.signalAndWait();
if (parent != null) {
// Close the fd via the parent stream's close method. The parent
// will reinvoke our close method, which is defined in the
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// that method will prevent this method from being reinvoked.
//
((java.io.Closeable)parent).close();
} else {
nd.close(fd);
}
}