美文网首页
java nio 在windows的实现

java nio 在windows的实现

作者: 不存在的里皮 | 来源:发表于2019-04-27 07:33 被阅读0次

0. 结论

先说结论吧。

  • jdk8和以前,java nio的windows实现,在底层是基于winsock2的select
  • 但是winsock2的select是否是基于轮询的,是不是我们常说的select/poll/epoll中的select,我无法查证,毕竟windows不是开源的。如果是轮询,那效率是相当低的。所以说windows就这点不好>_<。
  • 一次select可返回的最大数量是1024。

1. 在windows上的实现

参考java nio 在windows上的实现
很多人说是IOCP,其实是select。
首先我们一步步查看调用链:
Selector.select->...->WindowsSelectorImpl.doSelect->WindowsSelectorImpl.SubSelector.poll->WindowsSelectorImpl.SubSelector.poll0
我们看下WindowsSelectorImpl.SubSelector.poll:

private int poll() throws IOException {
  return this.poll0(WindowsSelectorImpl.this.pollWrapper.pollArrayAddress, Math.min(WindowsSelectorImpl.this.totalChannels, 1024), this.readFds, this.writeFds, this.exceptFds, WindowsSelectorImpl.this.timeout);
}

然后再看最后调用的WindowsSelectorImpl.SubSelector.poll0:

private native int poll0(long var1, int var3, int[] var4, int[] var5, int[] var6, long var7);

该函数是一个native方法,其源码需要到jdk源码中查看。但jdk不是开源的,所以native方法实现只能在openJdk中找。

参考OpenJDK与JDK的区别分析,openJdk只是在jdk上加了少许不痛不痒的功能而已,关于WindowsSelectorImpl的实现应该是一样的。

接下来我们找到openJdk的源码,查看winsock2$poll0

2. WindowsSelectorImpl

我们找到openJdk8的源码jdk8 WindowsSelectorImpl.c.shtml

2.1 调用winsock2$select

参考:

在WindowsSelectorImpl$poll0函数中我们看到:

if ((result = select(0 , &readfds, &writefds, &exceptfds, tv))
                                                             == SOCKET_ERROR)

所以调用的是winsock2的select方法,阻塞监听触发read/write事件的fd(这里的fd就是指socket)。激活读写事件的socket会保存在readfds和writefds中。
所以:

  • jdk8和以前,java nio的windows实现,在底层是基于winsock2的select
  • 但是winsock2的select是否是基于轮询的,是不是我们常说的select/poll/epoll中的select,我无法查证,毕竟windows不是开源的。如果是轮询,那效率是相当低的。所以说windows就这点不好>_<。

2.2 设置上层调用的返回值

之后有如下代码:

resultbuf[0] = readfds.fd_count;
for (i = 0; i < (int)readfds.fd_count; i++) {
   resultbuf[i + 1] = (int)readfds.fd_array[i];
}
(*env)->SetIntArrayRegion(env, returnReadFds, 0, readfds.fd_count + 1, resultbuf);

该段代码的作用,是把激活读事件的socket拷贝至returnReadFds中,作为上层调用的返回值。
附近格式类似的代码功能也一样,都是把激活read/write事件的socket拷贝到returnReadFds/returnWriteFds中,作为上层调用的返回值。如果有异常发生,则returnExceptFds也会被正确地被赋值。

2.3 selector的最大监听数

根据上一节,我们发现在poll0调用中,会传入参数this.readFds, this.writeFds, this.exceptFds,以便poll0设置返回值:

private int poll() throws IOException {
  return this.poll0(WindowsSelectorImpl.this.pollWrapper.pollArrayAddress, Math.min(WindowsSelectorImpl.this.totalChannels, 1024), this.readFds, this.writeFds, this.exceptFds, WindowsSelectorImpl.this.timeout);
}

其中this.readFds是成员函数,我们看到定义:

 private final class SubSelector {
        private final int pollArrayIndex;
        private final int[] readFds;
        private final int[] writeFds;
        private final int[] exceptFds;

以及其构造函数:


可以发现,readFds、writeFds、exceptFds都被赋予了固定长度的数组, 而且这个变量并没有再变换过。
readFds、writeFds、exceptFds的作用是接收触发相应事件的socket。
所以我认为,在windows中,selector一次监听返回的最大激活数目不能超过1024
不过在winsock2.h中,我看到:
typedef struct fd_set {
        u_int fd_count;               /* how many are SET? */
        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;

其中fd_set是returnReadFds、returnWriteFds的类型,也就是说fd_set是返回值参数的类型。
然后FD_SETSIZE的长度:

 #ifndef FD_SETSIZE
 #define  FD_SETSIZE      64 
 #endif  /* FD_SETSIZE */

意思非常明显,也就是说winsock默认最多处理64个sock。也可以通过#define修改FD_SETSIZE为想要的值。
我们回看jdk8的WindowsSelectorImpl.c,在开头就有一句:

#define FD_SETSIZE 1024

说明openJdk将这个限制改成了1024,与上文的数值一致。最后,我们再一次确认了这个限制是1024。

相关文章

  • java nio 深入探究(未完成)

    在windows上的实现 java nio 在windows的实现 jdk8和以前,java nio的window...

  • java nio 在windows的实现

    0. 结论 先说结论吧。 jdk8和以前,java nio的windows实现,在底层是基于winsock2的se...

  • java NIO详解

    Java NIO系列教程(1):Java NIO 概述 NIO学习系列:缓冲区内部实现机制 Java NIO系列教...

  • 多线程Reactor模式及Netty线程模型

    Netty是一款高效的NIO框架和工具,基于Java NIO实现,Java NIO的Selector给Reacto...

  • JAVA NIO SELECTOR

    JAVA SELECTOR Java NIO根据操作系统不同, 针对nio中的Selector有不同的实现java...

  • Java NIO

    一、NIO概述 NIO即 non-blocking IO,非阻塞IO,在java中实现主要通过Channel、Bu...

  • Java IO的基础操作书目录

    Java实现创建文件 Java重命名文件 Java实现删除文件 Java使用NIO删除文件 通过BufferedI...

  • NIO通讯模型

    Java NIO通讯模型在JDK 1.4时推出,在JDK层面对mac,windows,linux三个系统做了不同的...

  • 4.2.2、nio原理

    nio实现 我们知道使用java nio时会使用以下代码: open()的实现为: 这是使用了SelectorPr...

  • Tomcat NIO2 网络模型原理分

    tomcat NIO2是基于java jdk nio2实现的,想要弄明白tomcat的实现,我们必须要理解jdk ...

网友评论

      本文标题:java nio 在windows的实现

      本文链接:https://www.haomeiwen.com/subject/ophhnqtx.html