简述
本文主要介绍一下jdk1.6版本中的NIO Selector空轮询BUG,描述一下BUG的现象及原因,以及Netty中如何巧妙的规避了这个bug。
为什么要写这篇文章,说来惭愧,很久以前面试官问我,知道jdk空轮询问题吗,为什么会有这个问题,如何解决这个问题?我没答上来。。
Selector空轮询BUG
重现场景步骤
服务端等待连接
客户端发起连接,发送消息
服务端接受连接,并注册监听通道的OP_READ
服务端读取消息,从感兴趣事件集合中移除OP_READ
客户端关闭连接
服务端给客户端发送消息
服务端select方法不再阻塞,无限被唤醒并且返回值为0.
实验结果
在window上,此步骤下,是正常的。但是在linux机器上,selector陷入了死循环(cpu100%)。
bug根源
官方在6670302-BUG页面上好像并不认为是jdk的bug。也没给出具体原因。而把原因归结为Linux Kernel 2.4版本的bug(JDK-6481709)。官方认为linux 内核2.6版本解决这个bug并且也发行了4年了,更建议大家使用linux kernel2.6。
笔者愚钝,看了JDK-6481709这个BUG后,并没发现产生的原因。
问题产生于linux的epoll(显然是被甩锅了)。如果一个socket文件描述符,注册的事件集合码为0,然后连接突然被对端中断,那么epoll会被POLLHUP或者有可能是POLLERR事件给唤醒,并返回到事件集中去。这意味着,Select