自己对着源码敲一遍练习,写上注释。发现NIO编程难度好高啊。。 虽然很复杂,但是NIO编程的有点还是很多: 1、客户端发起的连接操作是异步的,可以通过在多路复用器注册OP_CONNECTION等待后续结果,不需要像BIO的客户端一样被同步阻塞。 ; 6 import java.nio.channels.SelectionKey; 7 import java.nio.channels.Selector; 8 import java.nio.channels.SocketChannel ; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.SelectionKey ; 7 import java.nio.channels.Selector; 8 import java.nio.channels.ServerSocketChannel; 9 import
1http访问流程 1 NioEndpoint.Acceptor等待客户端连接,客户端连接之后将SocketChannel转发给Poller 相关源码如下 /** * */ } catch (IOException ioe) { log.error(sm.getString("endpoint.nio.selectorCloseFail
hotspot:http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd 调用本地native方法 package sun.nio.ch true; break; } } return updated; } 调用方 package sun.nio.ch https://linux.die.net/man/2/epoll_wait http://www.man7.org/linux/man-pages/man2/epoll_wait.2.html 扩展阅读:NIO 源码分析(02-1) BIO 源码分析 NIO-EPollSelectorIpml源码分析 epoll源码实现分析[整理] epoll内核源码详解+自己总结的流程 这个是比较完整的注释。 epoll内核源码分析 一文看懂DPDK 内核是导致瓶颈的原因所在,要解决问题需要绕过内核。所以主流解决方案都是旁路网卡IO,绕过内核直接在用户态收发包来解决内核的瓶颈。 ?
玩java也有些年头,感觉对于nio的理解总是停留在IO复用的io模型,知其然但不知其所以然,故而今天来解开Java NIO的神秘面纱。 首先来回顾下NIO基本概念,Java NIO主要由Buffer、Channel、Selector三大组件组成。其他组件比如Pipe、FileLock只不过是这三个组件的公共工具类。 Buffer是与NIO Channel交互的载体,提供了一系列便于操作内存块的方法。读数据是从Channel读取到Buffer中,写数据是从Buffer写入到Channel。 DefaultSelectorProvider 通过阅读JDK源码 我们可以找到linux、macosx、windows三个版本的实现 linux版本: macosx版本: windows版本: 以Linux 为例 我们来接着一探究竟,通过源码可知Linux使用的Provider为:EPollSelectorProvider public class EPollSelectorProvider extends
代码@3 configureBlocking()调用本地函数IOUtil.c#Java_sun_nio_ch_IOUtil_configureBlocking(). int flags = fcntl( 小结:Java NIO的非阻塞通过本地函数fcntl中F_SETFL来设置。 代码@4 accept()调用本地函数ServerSocketChannelImpl.c#Java_sun_nio_ch_ServerSocketChannelImpl_accept0。 Java NIO Socket通道可以运行非阻塞模式以及可选择的,不必为每个socket连接新建一个线程,避免管理大量线程上下文切换的总开销;借助NIO类,一个或者几个线程就可以管理成百上千的活动socket 五、参考书籍 《Java NIO》、《UNIX网络编程 卷1》
(答案:只是说明它写入了内核的send_queue) java nio是水平触发的, 而且缓冲区超过"低水位"就触发读事件, 不超过"高水位"就触发写事件, 那这个水位到底多高? (没看native源码,但应该是socket的recv_queue和send_queue,反正我们只需要根据read和write的返回值、是否抛出异常来决定下一步行为即可。) 技术内幕》提到了可将写入的数据分成固定大小(比如8KB)的chunk,并以chunk为单位写入DirectBuffer IOUtil::writeFromNativeBuffer 没找到native源码 根据Java NIO read() End of Stream read返回-1代表的EOF,应该是说明对方优雅关闭了连接(比如对方正常发出FIN并响应之类的)。 引申地说,在nio编程时,如果ByteBuffer没有写完,不应当坚持循环等ByteBuffer写完。最好是注册写事件,等下一次写。
参考 NIO源码分析(一) Netty源码—三、select public static Selector open() throws IOException { return SelectorProvider.provider true; break; } } return updated; } updateRegistrations的源码不贴了 总结 java nio的底层机制是epoll 其底层关键方法是来自EPollArrayWrapper的native函数epollCreate, epollCtl和epollWait.
Java NIO Demo前面学习了socket,io模型及io多路复用的系统实现,这次想要学习的是Java NIO是如何利用epoll完成高并发网络框架的。 源码探索对源码不感兴趣的同学可以跳到下一个标题。epoll的三个核心方法在上篇文章做了介绍,分别是epoll_create,epoll_ctl,epoll_wait。 这个的源码还是比较好找的。 利用epoll的三个核心指令完成socket io 多路复用的源码探索完成。 总结这次主要学习了Java NIO和epoll是如何结合使用的,源码追索都比较枯燥,当搞清楚调用逻辑之后,还是挺兴奋的。
newBuffer.get()); @1 newBuffer拥有了与buffer相同的mark、position、limit @2 buffer执行clear后不会对newBuffer造成影响 Duplicate源码 2.非直接缓冲区 非直接缓冲区源码 ByteBuffer byteBuffer = ByteBuffer.allocate(10); // @1 public static ByteBuffer 例如:asCharBuffer()、asLongBuffer()等通过工厂类创建视图缓冲区见上文复制/分割缓冲区源码部分,下面以asCharBuffer()分析下如何转换的。 源码分析 public CharBuffer asCharBuffer() { int size = this.remaining() >> 1; int off = offset + 三、总结 本文从源码角度跟踪分析了复制缓冲区、只读缓冲区、分割缓冲区、字节顺序、非直接缓冲区、直接缓冲区、视图缓冲区的实现原理。 四、参考资料 《Java NIO》第二章(完)
long pipeFds = IOUtil.makePipe(false); staticnativelongmakePipe(boolean blocking); //IOUtil.c#Java_sun_nio_ch_IOUtil_makePipe () pipe(fd) 1.Pipe函数 IOUtil.makePipe本地方法调用IOUtil.c#Java_sun_nio_ch_IOUtil_makePipe()->pipe(fd). 六、系列文章 系统层面I/O【原理笔记】 系统五种I/O模型【原理笔记】 Java NIO缓存区基本操作【源码笔记】 Java NIO字节缓存区【源码笔记】 Java NIO通道概览与文件通道【 源码笔记】 Java NIO文件锁和可中断通道【源码笔记】 Java NIO 散布读与聚集写【源码笔记】 Java NIO套接字【源码笔记】
本文将介绍 Tomcat 中的 NIO 使用,使大家对 Java NIO 的生产使用有更加直观的认识。 虽然本文的源码篇幅也不短,但是 Tomcat 的源码毕竟不像 Doug Lea 的并发源码那么“变态”,对于大部分读者来说,阅读难度比之前介绍的其他并发源码要简单一些,所以读者不要觉得有什么压力。 目录 源码环境准备 Tomcat 9.0.6 下载地址:https://tomcat.apache.org/download-90.cgi 由于上面下载的 tomcat 的源码并没有使用 maven 进行组织 ,不方便我们看源码,也不方便我们进行调试。 打开 Http11NioProtocol 和 Http11Nio2Protocol源码,我们可以看到,在构造方法中,它们分别指定了 NioEndpoint 和 Nio2Endpoint。
概念关系: 0 <= mark <= position <= limit <= capacity 二、缓存区 1.Buffer类图 备注:从Buffer类图中体现的一系列操作方法,下文中将对其重要的方法源码逐一分析 @2 position需要小于等于limit;返回position后自增向后移位 @3 offset默认为0,可以在构造缓存区时对其赋值;每次填充时position需要加上offset 1.3 读取源码 position=8; limit=10; capacity=10 2.1.2 Flip后内存截图 备注:Flip后position=0; limit=8; capacity=10 2.1.3 Flip源码 4.4 压缩源码 public CharBuffer compact() { System.arraycopy(hb, ix(position()), hb, ix(0), remaining() this.put(src[i]); // @2 return this; } @1 批量写入的长度不能大于剩余元素 @2 将数组元素写入到buffer 四、参考资料 《Java NIO
想要使用NIO开发Socket分服务端和客户端,必须掌握的一个知识点就是ByteBuffer的使用,他是NIO在数据传输中的利器! 或者直接初始化数据创建 ByteBuffer wrapBuffer = ByteBuffer.wrap("欢迎关注公众号:【源码学徒】 学习更多源码知识!". 】 学习更多源码知识!". 的零拷贝#nio的堆外内存 ) 都已经介绍完毕,其他类似的API譬如 clear、mark、reset、rewind 再上面的外内内存的介绍中都已经介绍完毕了,逻辑都一样,感兴趣的小伙伴可以自己追一下源码 对于NIO的学习,这个缓冲区是必不可少的一节课!务必要搞明白呀! 欢迎关注源码学徒,一起学习,一起进步!
七、读取数据到ByteBuffer源码 给予fileChannel.read(buffer2)进行源码跟踪 1.JDK源码跟踪 代码位置:sun.nio.ch.FileChannelImpl public 2.Native源码跟踪 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz, 八、通道关闭源码 给予fileChannel.close()进行追踪 1.JDK源码追踪 代码位置:java.nio.channels.spi.AbstractInterruptibleChannel 十、参考资料 参考书籍:《Java NIO》第三章 文章总结:本文梳理了通道接口继承关系,以文件通道FileChannel的示例入手,跟踪每个操作的Native方法,以及给出这些Native方法的调用源码和说明 十一、系列文章 系统层面I/O【原理笔记】 Java NIO缓存区基本操作【源码笔记】 Java NIO字节缓存区【源码笔记】 ---- 「瓜农老梁 学习同行」
异步I/O Java NIO的底层实现 我们都知道Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要提供自己的Native版本的NIO呢? 明明Java NIO底层也是基于epoll调用(最新的版本)的.这里,我们先不明说,大家想一想可能的情况.下列的源码都来自于OpenJDK-8u40-b25版本. open方法 如果我们顺着Selector.open 二是看这么多源码,花费这么多时间有什么作用呢? 我感觉如果从非功利的角度来看,那么就是纯粹的希望了解的更多,有时候看完源码或在理解了底层原理之后,都会用一种恍然大悟的感觉,比如说AQS的原理.如果从目的性的角度来看,那么就是你知道底层原理之后,你的把握性就更强了 ,如果出了问题,你可以更快的找出来,并且解决.除此之外,你还可以按照具体的现实情况,以源码为模板在自己造轮子,实现一个更加符合你当前需求的版本.
异步I/O Java NIO的底层实现 我们都知道Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要提供自己的Native版本的NIO呢? 明明Java NIO底层也是基于epoll调用(最新的版本)的.这里,我们先不明说,大家想一想可能的情况.下列的源码都来自于OpenJDK-8u40-b25版本. open方法 如果我们顺着Selector.open 二是看这么多源码,花费这么多时间有什么作用呢? 我感觉如果从非功利的角度来看,那么就是纯粹的希望了解的更多,有时候看完源码或在理解了底层原理之后,都会用一种恍然大悟的感觉,比如说AQS的原理.如果从目的性的角度来看,那么就是你知道底层原理之后,你的把握性就更强了 ,如果出了问题,你可以更快的找出来,并且解决.除此之外,你还可以按照具体的现实情况,以源码为模板在自己造轮子,实现一个更加符合你当前需求的版本.
Java NIO的底层实现 我们都知道Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要提供自己的Native版本的NIO呢? 明明Java NIO底层也是基于epoll调用(最新的版本)的.这里,我们先不明说,大家想一想可能的情况.下列的源码都来自于OpenJDK-8u40-b25版本. open方法 如果我们顺着Selector.open 二是看这么多源码,花费这么多时间有什么作用呢? 我感觉如果从非功利的角度来看,那么就是纯粹的希望了解的更多,有时候看完源码或在理解了底层原理之后,都会用一种恍然大悟的感觉,比如说AQS的原理.如果从目的性的角度来看,那么就是你知道底层原理之后,你的把握性就更强了 ,如果出了问题,你可以更快的找出来,并且解决.除此之外,你还可以按照具体的现实情况,以源码为模板在自己造轮子,实现一个更加符合你当前需求的版本.
在上一篇博文中讲述了几种IO模型,现在我们开始进入Java NIO编程主题。NIO是Java 4里面提供的新的API,目的是用来解决传统IO的问题。 本文下面分别从Java NIO的几个基础概念介绍起。 一.NIO中的几个基础概念 在NIO中有几个比较关键的概念:Channel(通道),Buffer(缓冲区),Selector(选择器)。 Buffer(缓冲区),是NIO中非常重要的一个东西,在NIO中所有数据的读和写都离不开Buffer。 下面介绍一下NIO中最核心的一个东西:Selector。
目录 一、Native函数解读 1.矢量I/O结构体iovec 2.散布读readv() 3.聚集写writev() 二、Scatter/Gather接口 三、一个散布读示例 四、散布读JDK源码 1 .流程图 2.源码注释 五、文章总结 六、参考资料 一、Native函数解读 1.矢量I/O结构体iovec struct iovec { caddr_t iov_base; // @1 int 四、散布读JDK源码 由以上Native源码分析看出,矢量IO数据结构iovec是散布读和聚集写的核心部分,JDK源码实现也会围绕iovec结构体的封装展开。 1.流程图 ? IOV_MAX代码位置:jdk/src/solaris/native/sun/nio/ch JNIEXPORT jint JNICALL Java_sun_nio_ch_IOUtil_iovMax(JNIEnv 《Java NIO》 2.readv()函数说明 https://pubs.opengroup.org/onlinepubs/009695399/functions/readv.html 3.writev
文将介绍 Tomcat 中的 NIO 使用,使大家对 Java NIO 的生产使用有更加直观的认识。 虽然本文的源码篇幅也不短,但是 Tomcat 的源码毕竟不像 Doug Lea 的并发源码那么“变态”,对于大部分读者来说,阅读难度比之前介绍的其他并发源码要简单一些,所以读者不要觉得有什么压力。 源码环境准备 Tomcat 9.0.6 下载地址:https://tomcat.apache.org/download-90.cgi 由于上面下载的 tomcat 的源码并没有使用 maven 进行组织 ,不方便我们看源码,也不方便我们进行调试。 打开 Http11NioProtocol 和 Http11Nio2Protocol源码,我们可以看到,在构造方法中,它们分别指定了 NioEndpoint 和 Nio2Endpoint。