- 浏览: 979847 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
Reference定义(PhantomReference,Cleaner):http://donald-draper.iteye.com/blog/2371661
FileChanne定义:http://donald-draper.iteye.com/blog/2374149
文件读写方式简单综述:http://donald-draper.iteye.com/blog/2374237
文件读写方式简单综述后续(文件,流构造):http://donald-draper.iteye.com/blog/2374294
在看了FileChanne定义后,为了更好了理解FileChanne,我们简单的看了文件File,路径Path ,文件系统FileSystem,文件系统提供者FileSystemProvider。我们先回顾下相关概念:
File内部关联一个文件系统FileSystem,用于操作底层的系统,file的文件分隔符和路径分隔符都是从FileSystem获取,windows(\\,;)和unix(\,:)有所不同,FileSystem根据底层操作获取不同文件系统实现,windows默认为Win32FileSystem。file的创建,删除,list当前目录文件等待操作,实际是委托给Win32FileSystem。获取文件Path,首先获取文件的默认文件系统提供者,默认为WindowsFileSystemProvider,WindowsFileSystemProvider通过文件path(URI),创建文件Path(WindowsPath),这个主要用于创建文件通达需要。
今天我们来看一下通道的具体实现,从获取通道开始,获取通道有4中方法:
1.从FileOutputStream获取可写不可读文件通道
//FileOutputStream
2.从FileInputStream获取可读不可写文件通道
//FileInputStream
3.从RandomAccessFile获取可读可写文件通道
//RandomAccessFile
//FileChannelImpl
4.从文件系统提供者获取文件通道(FileChannel#open)
//FileChannel
//WindowsFileSystemProvider
再来看WindowsChannelFactory创建文件通道:
上述过程我们需要关注的有以下几点:
1.
2.
3.
下面分别来看:
1.
2.
来看这一步的关键点:
//WindowsNativeDispatcher
创建方法中我们还有两点要看
2.a
2.b
下面分别来看这两点:
再看这个之前先看一下NativeBuffer
//NativeBuffer
再回到刚才创建文件中的两点
2.a
//WindowsNativeDispatcher
2.b
//NativeBuffers
从以上a,b两点,我们需要关注的是getNativeBufferFromCache,allocNativeBuffer,releaseNativeBuffer方法,
下面我们单独来看一下NativeBuffers
3.
在这一步我们又看到了FileChannelImpl#open方法,这个我们在后面再看。
总结:
获取区文件的通道一共有四种,第一种从FileOutputStream获取写模式文件通道,第二种从FileInputStream获取读模式文件通道,第三种从RandomAccessFile获取读写模式文件通道,第四种调用FileChannelImpl#open方法,这个过程首先从参数文件Path(WindowsPath)获取文件系统的提供者,实际为WindowsFileSystemProvider,委托给WindowsFileSystemProvider创建文件通道,WindowsFileSystemProvider根据WindowsPath和,文件属性WindowsSecurityDescriptor(FileAttribute[]),和打开选项集,将实际创建通道任务交给WindowsChannelFactory,WindowsChannelFactory首先将打开选项装换为内部的通道配置标志Flags(读写模式(read,writer),同步方式(sync,dsync),append等),然后根据Flags,和Path信息等信息创建文件,创建文件实际由WindowsNativeDispatcher完成。WindowsNativeDispatcher首先从线程本地缓存获取NativeBuffer,将Path信息放在NativeBuffer中,然后创建文件,创建后,将NativeBuffer释放,即放入线程本地缓存,以便重用。具体选择哪种方式,根据需要选择。
FileChanne定义:http://donald-draper.iteye.com/blog/2374149
文件读写方式简单综述:http://donald-draper.iteye.com/blog/2374237
文件读写方式简单综述后续(文件,流构造):http://donald-draper.iteye.com/blog/2374294
在看了FileChanne定义后,为了更好了理解FileChanne,我们简单的看了文件File,路径Path ,文件系统FileSystem,文件系统提供者FileSystemProvider。我们先回顾下相关概念:
File内部关联一个文件系统FileSystem,用于操作底层的系统,file的文件分隔符和路径分隔符都是从FileSystem获取,windows(\\,;)和unix(\,:)有所不同,FileSystem根据底层操作获取不同文件系统实现,windows默认为Win32FileSystem。file的创建,删除,list当前目录文件等待操作,实际是委托给Win32FileSystem。获取文件Path,首先获取文件的默认文件系统提供者,默认为WindowsFileSystemProvider,WindowsFileSystemProvider通过文件path(URI),创建文件Path(WindowsPath),这个主要用于创建文件通达需要。
今天我们来看一下通道的具体实现,从获取通道开始,获取通道有4中方法:
1.从FileOutputStream获取可写不可读文件通道
//FileOutputStream
public FileChannel getChannel() { synchronized (this) { if (channel == null) { //可写不可读 channel = FileChannelImpl.open(fd, false, true, append, this); /* * Increment fd's use count. Invoking the channel's close() * method will result in decrementing the use count set for * the channel. */ fd.incrementAndGetUseCount(); } return channel; } }
2.从FileInputStream获取可读不可写文件通道
//FileInputStream
public FileChannel getChannel() { synchronized (this) { if (channel == null) { //可读不可写 channel = FileChannelImpl.open(fd, true, false, this); /* * Increment fd's use count. Invoking the channel's close() * method will result in decrementing the use count set for * the channel. */ fd.incrementAndGetUseCount(); } return channel; } }
3.从RandomAccessFile获取可读可写文件通道
//RandomAccessFile
public class RandomAccessFile implements DataOutput, DataInput, Closeable { private FileDescriptor fd; private FileChannel channel = null; private boolean rw;//是否读写 private Object closeLock = new Object(); private volatile boolean closed = false; private static final int O_RDONLY = 1; private static final int O_RDWR = 2; private static final int O_SYNC = 4; private static final int O_DSYNC = 8; /* @since 1.4 * @spec JSR-51 */ public final FileChannel getChannel() { synchronized (this) { if (channel == null) { //默认可读,在根据rw判断是否可写 channel = FileChannelImpl.open(fd, true, rw, this); /* * FileDescriptor could be shared by FileInputStream or * FileOutputStream. * Ensure that FD is GC'ed only when all the streams/channels * are done using it. * Increment fd's use count. Invoking the channel's close() * method will result in decrementing the use count set for * the channel. */ fd.incrementAndGetUseCount(); } return channel; } } ... }
//FileChannelImpl
public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, Object obj) { return new FileChannelImpl(filedescriptor, flag, flag1, false, obj); } public static FileChannel open(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj) { return new FileChannelImpl(filedescriptor, flag, flag1, flag2, obj); } private FileChannelImpl(FileDescriptor filedescriptor, boolean flag, boolean flag1, boolean flag2, Object obj) { fd = filedescriptor; readable = flag;//可读标志 writable = flag1;//可写标志 append = flag2;//是否尾部追加文件,默认为fasle //创建文件通道的对象,为FileInput/OutputStream, //RandomAccessFile获取FileSystemProvider(WindowsFileSystemProvider) parent = obj; nd = new FileDispatcherImpl(flag2); }
4.从文件系统提供者获取文件通道(FileChannel#open)
//FileChannel
//根据文件Path和打开选项创建文件通道 public static FileChannel open(Path path, OpenOption... options) throws IOException { Set<OpenOption> set = new HashSet<OpenOption>(options.length); Collections.addAll(set, options); //委托给 FileChannel open(Path path, Set<? extends OpenOption> options,FileAttribute<?>... attrs) return open(path, set, NO_ATTRIBUTES); } //根据文件Path,打开选项,及文件属性创建文件通道 public static FileChannel open(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException { //这一步我们在前面一篇文章已讲,文件系统提供者为WindowsFileSystemProvider FileSystemProvider provider = path.getFileSystem().provider(); return provider.newFileChannel(path, options, attrs); }
//WindowsFileSystemProvider
public transient FileChannel newFileChannel(Path path, Set set, FileAttribute afileattribute[]) throws IOException { WindowsPath windowspath;//文件Path WindowsSecurityDescriptor windowssecuritydescriptor;//文件属性描述 if(path == null) throw new NullPointerException(); if(!(path instanceof WindowsPath)) throw new ProviderMismatchException(); windowspath = (WindowsPath)path; windowssecuritydescriptor = WindowsSecurityDescriptor.fromAttribute(afileattribute); 我们需要关注的是这一点 FileChannel filechannel = WindowsChannelFactory.newFileChannel(windowspath.getPathForWin32Calls(), windowspath.getPathForPermissionCheck(), set, windowssecuritydescriptor.address()); if(windowssecuritydescriptor != null) windowssecuritydescriptor.release(); return filechannel; ... windowsexception.rethrowAsIOException(windowspath); ... Exception exception; exception; if(windowssecuritydescriptor != null) windowssecuritydescriptor.release(); throw exception; }
再来看WindowsChannelFactory创建文件通道:
class WindowsChannelFactory { private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); static final OpenOption OPEN_REPARSE_POINT = new OpenOption() {}; private WindowsChannelFactory() { } static FileChannel newFileChannel(String s, String s1, Set set, long l) throws WindowsException { //转换打开选项集为Flags Flags flags = Flags.toFlags(set); if(!flags.read && !flags.write) if(flags.append) flags.write = true; else flags.read = true; //可读可append,抛出选项配置错误 if(flags.read && flags.append) throw new IllegalArgumentException("READ + APPEND not allowed"); //可append,存在压缩抛出选项配置错误 if(flags.append && flags.truncateExisting) { throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); } else { //创建文件描述符 FileDescriptor filedescriptor = open(s, s1, flags, l); //委托给FileChannelImpl return FileChannelImpl.open(filedescriptor, flags.read, flags.write, flags.append, null); } } }
上述过程我们需要关注的有以下几点:
1.
//转换打开选项集为Flags Flags flags = Flags.toFlags(set);
2.
//创建文件描述符 FileDescriptor filedescriptor = open(s, s1, flags, l);
3.
//委托给FileChannelImpl return FileChannelImpl.open(filedescriptor, flags.read, flags.write, flags.append, null);
下面分别来看:
1.
//转换打开选项集为Flags Flags flags = Flags.toFlags(set);
//WindowsChannelFactory - Flags private static class Flags { boolean read;//是否可读 boolean write;//是否可写 boolean append;//追加文件 boolean truncateExisting;//存在,则压缩 boolean create;//文件不存在,则创建 boolean createNew;//无论文件不在与否,创建文件 boolean deleteOnClose;//关闭文件删除,可用于创建临时文件 boolean sparse;//是否稀疏文件 boolean overlapped; boolean sync;//同步文件更新(内容及元数据)到底层文件 boolean dsync;同步文件更新(内容)到底层文件 boolean shareRead;//共享读 boolean shareWrite;//贡献写 boolean shareDelete;//共享删除 boolean noFollowLinks; boolean openReparsePoint; private Flags() { shareRead = true; shareWrite = true; shareDelete = true; } //将打开选项集转化为Flags static Flags toFlags(Set set) { Flags flags = new Flags(); //遍历打开选项集,转化选项配置为Flags对应的field for(Iterator iterator = set.iterator(); iterator.hasNext();) { OpenOption openoption = (OpenOption)iterator.next(); //标准打开选项和拓展打开选项的配置转化类,将配置转化为Int,类型 static class _cls2 { static final int $SwitchMap$java$nio$file$StandardOpenOption[]; static final int $SwitchMap$com$sun$nio$file$ExtendedOpenOption[]; static { $SwitchMap$com$sun$nio$file$ExtendedOpenOption = new int[ExtendedOpenOption.values().length]; try { $SwitchMap$com$sun$nio$file$ExtendedOpenOption[ExtendedOpenOption.NOSHARE_READ.ordinal()] = 1; } catch(NoSuchFieldError nosuchfielderror) { } try { $SwitchMap$com$sun$nio$file$ExtendedOpenOption[ExtendedOpenOption.NOSHARE_WRITE.ordinal()] = 2; } catch(NoSuchFieldError nosuchfielderror1) { } try { $SwitchMap$com$sun$nio$file$ExtendedOpenOption[ExtendedOpenOption.NOSHARE_DELETE.ordinal()] = 3; } catch(NoSuchFieldError nosuchfielderror2) { } $SwitchMap$java$nio$file$StandardOpenOption = new int[StandardOpenOption.values().length]; try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.READ.ordinal()] = 1; } catch(NoSuchFieldError nosuchfielderror3) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.WRITE.ordinal()] = 2; } catch(NoSuchFieldError nosuchfielderror4) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.APPEND.ordinal()] = 3; } catch(NoSuchFieldError nosuchfielderror5) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.TRUNCATE_EXISTING.ordinal()] = 4; } catch(NoSuchFieldError nosuchfielderror6) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.CREATE.ordinal()] = 5; } catch(NoSuchFieldError nosuchfielderror7) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.CREATE_NEW.ordinal()] = 6; } catch(NoSuchFieldError nosuchfielderror8) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.DELETE_ON_CLOSE.ordinal()] = 7; } catch(NoSuchFieldError nosuchfielderror9) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.SPARSE.ordinal()] = 8; } catch(NoSuchFieldError nosuchfielderror10) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.SYNC.ordinal()] = 9; } catch(NoSuchFieldError nosuchfielderror11) { } try { $SwitchMap$java$nio$file$StandardOpenOption[StandardOpenOption.DSYNC.ordinal()] = 10; } catch(NoSuchFieldError nosuchfielderror12) { } } } //标准打开选项 if(openoption instanceof StandardOpenOption) switch(_cls2..SwitchMap.java.nio.file.StandardOpenOption[((StandardOpenOption)openoption).ordinal()]) { case 1: // '\001' flags.read = true; break; case 2: // '\002' flags.write = true; break; case 3: // '\003' flags.append = true; break; case 4: // '\004' flags.truncateExisting = true; break; case 5: // '\005' flags.create = true; break; case 6: // '\006' flags.createNew = true; break; case 7: // '\007' flags.deleteOnClose = true; break; case 8: // '\b' flags.sparse = true; break; case 9: // '\t' flags.sync = true; break; case 10: // '\n' flags.dsync = true; break; default: throw new UnsupportedOperationException(); } else //拓展打开选项 if(openoption instanceof ExtendedOpenOption) switch(_cls2..SwitchMap.com.sun.nio.file.ExtendedOpenOption[((ExtendedOpenOption)openoption).ordinal()]) { case 1: // '\001' flags.shareRead = false; break; case 2: // '\002' flags.shareWrite = false; break; case 3: // '\003' flags.shareDelete = false; break; default: throw new UnsupportedOperationException(); } else if(openoption == LinkOption.NOFOLLOW_LINKS) flags.noFollowLinks = true; else if(openoption == WindowsChannelFactory.OPEN_REPARSE_POINT) flags.openReparsePoint = true; else if(openoption == null) throw new NullPointerException(); else throw new UnsupportedOperationException(); } return flags; } }
2.
//创建文件描述符 FileDescriptor filedescriptor = open(s, s1, flags, l);
private static FileDescriptor open(String s, String s1, Flags flags, long l) throws WindowsException { boolean flag = false; int i = 0;//标准配置项,读写配置 if(flags.read) i |= -2147483648; if(flags.write) i |= 1073741824; int j = 0;//扩展配置项共享读写删除配置 if(flags.shareRead) j |= 1; if(flags.shareWrite) j |= 2; if(flags.shareDelete) j |= 4; int k = 128;//记录createNew,create,truncateExisting,dsync,sync,overlapped,deleteOnClose byte byte0 = 3; if(flags.write) if(flags.createNew) { byte0 = 1; k |= 2097152; } else { if(flags.create) byte0 = 4; if(flags.truncateExisting) if(byte0 == 4) flag = true; else byte0 = 5; } if(flags.dsync || flags.sync) k |= -2147483648; if(flags.overlapped) k |= 1073741824; if(flags.deleteOnClose) k |= 67108864; boolean flag1 = true;//记录noFollowLinks,openReparsePoint,deleteOnClose if(byte0 != 1 && (flags.noFollowLinks || flags.openReparsePoint || flags.deleteOnClose)) { if(flags.noFollowLinks || flags.deleteOnClose) flag1 = false; k |= 2097152; } if(s1 != null) { SecurityManager securitymanager = System.getSecurityManager(); if(securitymanager != null) { //检查读写删除权限 if(flags.read) securitymanager.checkRead(s1); if(flags.write) securitymanager.checkWrite(s1); if(flags.deleteOnClose) securitymanager.checkDelete(s1); } } //创建文件 long l1 = WindowsNativeDispatcher.CreateFile(s, i, j, l, byte0, k); ... FileDescriptor filedescriptor = new FileDescriptor(); //设置文件描述的处理器 fdAccess.setHandle(filedescriptor, l1); return filedescriptor; }
来看这一步的关键点:
//创建文件 long l1 = WindowsNativeDispatcher.CreateFile(s, i, j, l, byte0, k);
//WindowsNativeDispatcher
static long CreateFile(String s, int i, int j, int k, int l) throws WindowsException { return CreateFile(s, i, j, 0L, k, l); } static long CreateFile(String s, int i, int j, long l, int k, int i1) throws WindowsException { //将文件Path信息,放在本地buffer中 NativeBuffer nativebuffer = asNativeBuffer(s); long l1 = CreateFile0(nativebuffer.address(), i, j, l, k, i1); //释放nativebuffer,放入线程本地缓存,以便重用 nativebuffer.release(); return l1; Exception exception; exception; nativebuffer.release(); throw exception; } private static native long CreateFile0(long l, int i, int j, long l1, int k, int i1) throws WindowsException;
创建方法中我们还有两点要看
2.a
//将文件Path信息,放在本地buffer中 NativeBuffer nativebuffer = asNativeBuffer(s);
2.b
//释放nativebuffer,放入线程本地缓存,以便重用 nativebuffer.release();
下面分别来看这两点:
再看这个之前先看一下NativeBuffer
//NativeBuffer
class NativeBuffer { private static final Unsafe unsafe = Unsafe.getUnsafe(); private final long address;//内存地址 private final int size;//内存size private final Cleaner cleaner;//清理器 private Object owner;//buffer拥有者 private static class Deallocator implements Runnable { public void run() { //释放本地buffer空间 NativeBuffer.unsafe.freeMemory(address); } private final long address; Deallocator(long l) { address = l; } } NativeBuffer(int i) { address = unsafe.allocateMemory(i); size = i; cleaner = Cleaner.create(this, new Deallocator(address)); } void release() { NativeBuffers.releaseNativeBuffer(this); } long address() { return address; } int size() { return size; } Cleaner cleaner() { return cleaner; } void setOwner(Object obj) { owner = obj; } Object owner() { return owner; } }
再回到刚才创建文件中的两点
2.a
//将文件Path信息,放在本地buffer中 NativeBuffer nativebuffer = asNativeBuffer(s);
//WindowsNativeDispatcher
static NativeBuffer asNativeBuffer(String s) { int i = s.length() << 1; int j = i + 2; //从线程本地缓冲获取本地buffer NativeBuffer nativebuffer = NativeBuffers.getNativeBufferFromCache(j); //如果获取本地buffer为空,则创建一个 if(nativebuffer == null) nativebuffer = NativeBuffers.allocNativeBuffer(j); else//不为null,检查本地buffer的拥有者,是则直接返回 if(nativebuffer.owner() == s) return nativebuffer; char ac[] = s.toCharArray(); //否则,拷贝buffer内存 unsafe.copyMemory(ac, Unsafe.ARRAY_CHAR_BASE_OFFSET, null, nativebuffer.address(), i); unsafe.putChar(nativebuffer.address() + (long)i, '\0'); //设置buffer的拥有者 nativebuffer.setOwner(s); return nativebuffer; }
2.b
//释放nativebuffer,放入线程本地缓存,以便重用 nativebuffer.release();
//NativeBuffers
void release() { //委托给NativeBuffers NativeBuffers.releaseNativeBuffer(this); }
从以上a,b两点,我们需要关注的是getNativeBufferFromCache,allocNativeBuffer,releaseNativeBuffer方法,
下面我们单独来看一下NativeBuffers
class NativeBuffers { private static native void initIDs(); private static final Unsafe unsafe = Unsafe.getUnsafe(); static { //在当前线程访问控制权限下,加载net和nio库 AccessController.doPrivileged(new PrivilegedAction() { public Void run() { System.loadLibrary("net"); System.loadLibrary("nio"); return null; } public volatile Object run() { return run(); } }); initIDs(); } private NativeBuffers() { } private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int TEMP_BUF_POOL_SIZE = 3;//临时buffer private static ThreadLocal threadLocal = new ThreadLocal();//存放线程本地buffer static final boolean $assertionsDisabled = !sun/nio/fs/NativeBuffers.desiredAssertionStatus(); //从线程本地缓存获取NativeBuffer static NativeBuffer getNativeBufferFromCache(int i) { //从线程本地缓存获取NativeBuffer数组 NativeBuffer anativebuffer[] = (NativeBuffer[])threadLocal.get(); if(anativebuffer != null) { for(int j = 0; j < 3; j++) { NativeBuffer nativebuffer = anativebuffer[j]; if(nativebuffer != null && nativebuffer.size() >= i) { //返回线程本地缓存NativeBuffer数组中,第一个可用的NativeBuffer(容量大于i), //将NativeBuffer数组index索引对应的置null anativebuffer[j] = null; return nativebuffer; } } } return null; } //创建本地buffer static NativeBuffer allocNativeBuffer(int i) { if(i < 2048) i = 2048; //size最小为2M return new NativeBuffer(i); } //获取容量大于等于i的NativeBuffer static NativeBuffer getNativeBuffer(int i) { //从线程本地缓存获取NativeBuffer NativeBuffer nativebuffer = getNativeBufferFromCache(i); if(nativebuffer != null) { //拥有者不为null,则置null nativebuffer.setOwner(null); return nativebuffer; } else { //否则创建一个NativeBuffer return allocNativeBuffer(i); } } //将字节序列存放到NativeBuffer static NativeBuffer asNativeBuffer(byte abyte0[]) { //从线程本地缓存获取NativeBuffer NativeBuffer nativebuffer = getNativeBuffer(abyte0.length + 1); //拷贝字符串到nativebuffer copyCStringToNativeBuffer(abyte0, nativebuffer); return nativebuffer; } //拷贝字符串到nativebuffer static void copyCStringToNativeBuffer(byte abyte0[], NativeBuffer nativebuffer) { long l = Unsafe.ARRAY_BYTE_BASE_OFFSET; long l1 = abyte0.length; //断言开启,断言nativebuffer容量是否够用,不够用,则抛AssertionError if(!$assertionsDisabled && (long)nativebuffer.size() < l1 + 1L) { throw new AssertionError(); } else { unsafe.copyMemory(abyte0, l, null, nativebuffer.address(), l1); unsafe.putByte(nativebuffer.address() + l1, (byte)0); return; } } //释放nativebuffer static void releaseNativeBuffer(NativeBuffer nativebuffer) { //从线程本地缓存获取NativeBuffer数组 NativeBuffer anativebuffer[] = (NativeBuffer[])threadLocal.get(); if(anativebuffer == null) { //如果数组为空,则创长度为3的NativeBuffer数组,并将nativebuffer放入缓存中 anativebuffer = new NativeBuffer[3]; anativebuffer[0] = nativebuffer; //将NativeBuffer数组添加到线程本地缓存 threadLocal.set(anativebuffer); return; } //NativeBuffer数组不为null for(int i = 0; i < 3; i++) if(anativebuffer[i] == null) { //将nativebuffer放到线程本地缓冲NativeBuffer数组, //索引对应的NativeBuffer为null的位置上 anativebuffer[i] = nativebuffer; return; } //如果NativeBuffer的元素没有为null的,则将nativebuffer放在第一个容量小于它的index上, //并释放小于nativebuffer的内存空间 for(int j = 0; j < 3; j++) { NativeBuffer nativebuffer1 = anativebuffer[j]; //将 if(nativebuffer1.size() < nativebuffer.size()) { nativebuffer1.cleaner().clean(); anativebuffer[j] = nativebuffer; return; } } //释放nativebuffer内存空间 nativebuffer.cleaner().clean(); } //这里之所以将释放的NativeBuffer放在线程本地缓存中,主要为了重用NativeBuffer,因为NativeBuffer直接操作底层 内存,创建一个要耗费一定的系统资源。 }
3.
//委托给FileChannelImpl return FileChannelImpl.open(filedescriptor, flags.read, flags.write, flags.append, null);
在这一步我们又看到了FileChannelImpl#open方法,这个我们在后面再看。
总结:
获取区文件的通道一共有四种,第一种从FileOutputStream获取写模式文件通道,第二种从FileInputStream获取读模式文件通道,第三种从RandomAccessFile获取读写模式文件通道,第四种调用FileChannelImpl#open方法,这个过程首先从参数文件Path(WindowsPath)获取文件系统的提供者,实际为WindowsFileSystemProvider,委托给WindowsFileSystemProvider创建文件通道,WindowsFileSystemProvider根据WindowsPath和,文件属性WindowsSecurityDescriptor(FileAttribute[]),和打开选项集,将实际创建通道任务交给WindowsChannelFactory,WindowsChannelFactory首先将打开选项装换为内部的通道配置标志Flags(读写模式(read,writer),同步方式(sync,dsync),append等),然后根据Flags,和Path信息等信息创建文件,创建文件实际由WindowsNativeDispatcher完成。WindowsNativeDispatcher首先从线程本地缓存获取NativeBuffer,将Path信息放在NativeBuffer中,然后创建文件,创建后,将NativeBuffer释放,即放入线程本地缓存,以便重用。具体选择哪种方式,根据需要选择。
发表评论
-
文件通道解析二(文件锁,关闭通道)
2017-05-16 23:17 1063文件通道解析一(读写操作,通道数据传输等):http://do ... -
文件通道解析一(读写操作,通道数据传输等)
2017-05-16 10:04 1163Reference定义(PhantomRefere ... -
文件读写方式简单综述后续(文件,流构造)
2017-05-14 23:04 1479Java Socket通信实例:http://donald-d ... -
文件读写方式简单综述
2017-05-14 11:13 1135Java Socket通信实例:http://donald-d ... -
FileChanne定义
2017-05-12 23:28 936文件读写方式简单综述:http://donald-draper ... -
SeekableByteChannel接口定义
2017-05-11 08:43 1233ByteChannel,分散聚集通道接口的定义(SocketC ... -
FileChannel示例
2017-05-11 08:37 991前面我们看过socket通道,datagram通道,以管道Pi ... -
PipeImpl解析
2017-05-11 08:41 932ServerSocketChannel定义:http://do ... -
Pipe定义
2017-05-10 09:07 903Channel接口定义:http://donald-drape ... -
NIO-Pipe示例
2017-05-10 08:47 904PipeImpl解析:http://donald-draper ... -
DatagramChannelImpl 解析四(地址绑定,关闭通道等)
2017-05-10 08:27 776DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析三(多播)
2017-05-10 08:20 1891DatagramChannelImpl 解析一(初始化):ht ... -
NIO-UDP实例
2017-05-09 12:32 1583DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析二(报文发送与接收)
2017-05-09 09:03 1404DatagramChannelImpl 解析一(初始化):ht ... -
DatagramChannelImpl 解析一(初始化)
2017-05-08 21:52 1406Channel接口定义:http://donald-drape ... -
MembershipKeyImpl 简介
2017-05-08 09:11 922MembershipKey定义:http://donald-d ... -
DatagramChannel定义
2017-05-07 23:13 1227Channel接口定义:http://donald-drape ... -
MulticastChanne接口定义
2017-05-07 13:45 1136NetworkChannel接口定义:ht ... -
MembershipKey定义
2017-05-06 16:20 915package java.nio.channels; i ... -
SocketChannelImpl 解析四(关闭通道等)
2017-05-05 08:38 2527SocketChannelImpl 解析一(通道连接,发送数据 ...
相关推荐
“网络资源模型文件格式综述”章节深入讨论了网络资源模型的采集机制,这是理解网络状态和性能的关键。它通常包括定期或事件触发的数据收集,用于形成全面的网络视图。文件格式部分则详细描述了如何组织这些数据,以...
标题中的"link-(1).rar_Links...总结来说,"link-(1).rar_Links"这个压缩包提供了一条通往学术资源的通道,用户需要掌握一定的文件操作技巧,理解链接背后可能涉及的版权和使用限制,同时利用这些资源进行学习和研究。
- **临时文件**:创建临时文件的方法。 - **标准I/O的替代软件**:其他I/O库。 #### 第6章:系统数据文件和信息 - **口令文件**:存储用户账户信息的文件。 - **阴影口令**:安全增强技术。 - **组文件**:存储组...
从文件的概述来看,EMC公司发布了一系列与FCoE相关的白皮书,提供了FCoE的详尽综述。白皮书不仅概述了FCoE技术的现状,还对构成FCoE生态系统的硬件和软件组件进行了描述,并展望了这项技术在未来几年的发展方向。 ...
- **新建工程**:创建新项目文件。 - **建立用户**:设置访问权限。 - **新建节点**:定义系统结构。 - **建立通道库**:存储输入输出通道信息。 ##### 5. 建立实时数据库 - **配置变量属性**:定义变量类型、地址...
- **通道配置**: 定义每个I/O通道的特性。 - **Profibus/CAN模块配置**: 对于支持这些协议的PLC,配置相应的模块。 **6.7 任务配置** 任务配置用于管理程序的执行周期和优先级,包括: - **周期任务**: 定期执行的...
1. **图像预处理**:首先,对原始图像进行预处理,如灰度化,确保图像为单通道。这是因为分形压缩主要针对灰度图像,虽然也可以扩展到彩色图像,但处理过程会更复杂。 2. **分形域划分**:将图像划分为多个相同大小...
这种方式通常采用光纤通道或其他高速网络连接。 **2.2.3 Server-Free备份** Server-Free备份是指直接将数据从客户端传输到备份介质,无需经过服务器处理。这种方式可以显著减少服务器的负载。 **2.2.4 Server-...
- **创建POM文件**:指导如何构建项目的Maven POM文件,包括依赖管理、插件配置等内容。 - **添加classpath依赖**:具体说明哪些依赖是必须的,以及如何正确添加这些依赖。 - **编写代码**:通过示例代码展示如何...
政企合作将成为现代农业产业园发展的主流开发模式,政府会将产业园的部分建设任务以特许经营权的方式交给企业,通过政府引导和企业运营的合作共赢方式,促进园区的可持续健康发展。 农业物联网技术的应用是提高农业...
- **通道配置**:设置信号传输通道。 - **Profibus模块配置**:配置Profibus通讯模块。 - **CAN模块配置**:配置CAN通讯模块。 - **Can驱动器配置**:配置Can驱动器。 - **在线模式下的PLC配置**:实现实时通信和...
- **文件类型**:根据工程需求,可以创建C/C++源文件、汇编文件等。 - **作用**:编写具体的程序逻辑。 ##### 2.2.3 添加文件到工程 - **操作**:将已有的文件添加到当前工程中。 - **意义**:便于管理和编译多个...
- **SAN集中存储**:通过光纤通道或iSCSI连接,实现虚拟机文件的共享和高可用性。 - **集中管理、自动化及优化运行**:使用vCenter Server进行全局监控、资源调度和自动化操作,如vMotion动态迁移虚拟机,确保资源...
- **程序编辑**:涉及HTP和LTP通道的概念,支持单步与多步程序的创建、编辑、复制和移动,以及重演时间与推杆同步的调整,满足复杂演出的编程需求。 #### 直选场景与剧场模式 - **直选场景**:即快照SNAPSHOT功能...
- 使用远程系统创建复制会话时,可能出现系统计时问题导致的复制会话创建错误。 对于这些已知的问题,白皮书提供了详细的症状描述、解决方法,并提供了相关的跟踪编号,方便用户查询和跟踪问题的处理进度。 #### ...
国家对于现代农业产业园区的发展十分重视,自2016年起开始规范其发展,并在2017年中央一号文件中提出了具体的发展指示。现代农业产业园按照“生产+加工+科技”的模式建设,将技术集成、产业融合、创业平台和核心...