java nio的一个严重BUG

Posted on 2009-09-28 19:27 dennis 阅读(4588) 评论(5)  编辑  收藏 所属分类: java 、源码解读 

    这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,具体的详情可以看这里http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933 。令人失望的是这个BUG直到jdk
6u4才解决,sun的拖沓让人难以相信。这个BUG在server端容易出现,因为server端有频繁地接入断开连接。

    

    使用jdk 6u4之前版本的nio框架都有这个隐患,除非你的框架很好地处理了这个可能的隐患。Grizzly的处理方式比较简单,也就是BUG报告里面提到的方式,在SelectionKey.cancel()之后马上进行了一次select调用将fd从poll(epoll)中移除:

this.selectionKey.cancel();

try {

            // cancel key,then select now to remove file descriptor

            this.selector.selectNow();

 } catch (IOException e) {

         onException(e);

        log.error("Selector selectNow fail", e);

}

实际上这样的解决方式还是留有隐患的,因为key的取消和这个selectNow操作很可能跟Selector.select操作并发地在进行,在两个操作之间仍然留有一个极小的时间窗口可能发生这个BUG。因此,你需要更安全地方式处理这个问题,jetty的处理方式是这样,连续的select(timeout)操作没有阻塞并返回0,并且次数超过了一个指定阀值,那么就遍历整个key set,将key仍然有效并且interestOps等于0的所有key主动取消掉;如果在这次修正后,仍然继续出现select(timeout)不阻塞并且返回0的情况,那么就重新创建一个新的Selector,并将Old
Selector的有效channel和对应的key转移到新的Selector上,

                    long before=now;

                    int selected=selector.select(wait);

                    now = System.currentTimeMillis();

                    _idleTimeout.setNow(now);

                    _timeout.setNow(now);



                    // Look for JVM bugs

                    // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933

                    if (__JVMBUG_THRESHHOLD>0 && selected==0 && wait>__JVMBUG_THRESHHOLD && (now-before)<(wait/2) )

                    {

                        _jvmBug++;

                        if (_jvmBug>=(__JVMBUG_THRESHHOLD2))

                        {

                            synchronized (this)

                            {

                                _lastJVMBug=now;

                                                    // BLOODY SUN BUG !!!  Try refreshing the entire selector.

                                final Selector new_selector = Selector.open();

                                for (SelectionKey k: selector.keys())

                                {

                                    if (!k.isValid() || k.interestOps()==0)

                                        continue;

                                    

                                    final SelectableChannel channel = k.channel();

                                    final Object attachment = k.attachment();

                                    

                                    if (attachment==null)

                                        addChange(channel);

                                    else

                                        addChange(channel,attachment);

                                }

                                _selector.close();

                                _selector=new_selector;

                                _jvmBug=0;

                                return;

                            }

                        }

                        else if (_jvmBug==__JVMBUG_THRESHHOLD || _jvmBug==__JVMBUG_THRESHHOLD1)

                        {

                            // Cancel keys with 0 interested ops

                            for (SelectionKey k: selector.keys())

                            {

                                if (k.isValid()&&k.interestOps()==0)

                                {

                                    k.cancel();

                                }

                            }

                            return;

                        }

                    }

                    else

                        _jvmBug=0;

这个方案能比较好的在jdk 6u4之前的版本上解决这个BUG可能导致的问题。Mina和Netty没有看到有处理这个BUG的代码,如果我看错了,请留言告诉我。Yanf4j一直采用的是grizzly的方式,准备加上jetty的处理方案。当然,最简单的方案就是升级你的JDK :D


评论

# re:
java nio的一个严重BUG  回复  更多评论

2009-09-28 19:59 by lizongbo

nio还有几个严重的bug,在实际运行中碰到了,sun在u18才修复,而现在u18还没正式发布。 



https://jdk6.dev.java.net/6uNea.html 

http://download.java.net/jdk6/6u18/promoted/b01/changes/JDK6u18.b01.list.html 



例如:http://bugs.sun.com/view_bug.do?bug_id=6693490 


# re:
java nio的一个严重BUG  回复  更多评论

2009-09-28 20:19 by dennis

@lizongbo



看到了,6u3这个版本似乎问题多多。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6670302 这个BUG跟我这里描述的相似,解决的方法也是一样。

# re:
java nio的一个严重BUG  回复  更多评论

2009-09-28 20:49 by dennis

http://bugs.sun.com/view_bug.do?bug_id=6693490 这个BUG,一个间接影响也是关闭的channel一直有ready事件,select不阻塞并立即返回0,也就是导致CPU
100%,同样也是可以通过这里描述的方案解决的。

# re:
java nio的一个严重BUG  回复  更多评论

2009-09-29 21:32 by 喜乐递

最简单的方案就是升级你的JDK

# re:
java nio的一个严重BUG  回复  更多评论

2012-05-09 16:54 by hengyunabc

原来是nio的bug。。

以前也遇到过,在windows下测试了好久的程序,到linux下就出问题了,cpu跑满。

结果我是用每次select都用最新的SelectionKey来替换以前的SelectionKey,貌似没再出现cpu跑满的情况。

java nio的一个严重BUG的更多相关文章

  1. java nio的一个严重BUG(转)

    这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,具体的详情可以看这里http://bugs.sun.com/bugdatabase/view_bug.do ...

  2. java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多

    java nio 写一个完整的http服务器  支持文件上传   chunk传输    gzip 压缩      也仿照着 netty处理了NIO的空轮询BUG        本项目并不复杂 代码不多 ...

  3. Java多线程:Linux多路复用,Java NIO与Netty简述

    JVM的多路复用器实现原理 Linux 2.5以前:select/poll Linux 2.6以后: epoll Windows: IOCP Free BSD, OS X: kqueue 下面仅讲解L ...

  4. Java - NIO

    java.nio:NIO-2: NIO 面向流的IO体系一次只能处理一个或多个字节/字符,直至读取所有字节/符,且流中的数据不能前后移动.效率低,当数据源中没有数据时会阻塞线程.Java-4提供的新A ...

  5. java nio 与io区别

    转自:http://blog.csdn.net/keda8997110/article/details/19549493 当学习了Java NIO和IO的API后,一个问题马上涌入脑海: 我应该何时使 ...

  6. [翻译]java nio 概述

    原文地址:http://tutorials.jenkov.com/java-nio/overview.html java NIO 包含一下核心内容: Channels Buffers Selector ...

  7. Java NIO之Selector

    选择器是JavaNIO重磅推出的一个概念:在旧有的系统中为了跟踪多端口消息,需要为每一个端口配备一个线程做监听:但是有了selector就不需要了,一个Selector可以管理一众渠道(channel ...

  8. Java NIO中核心组成和IO区别

    1.Java NIO核心组件 Java NIO中有很多类和组件,包括Channel,Buffer 和 Selector 构成了核心的API.其它组件如Pipe和FileLock是与三个核心组件共同使用 ...

  9. Java NIO与IO

    当学习了Java NIO和IO的API后,一个问题立即涌入脑海: 我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异.它们的使用场景,以及它们怎样影响您的代 ...

随机推荐

  1. R语言入门视频笔记--1

    一.数据框简要 可输入来访问mtcars这个系统自带的数据框中的mpg列 mtcars$mpg 或者输入 mtcars[c("mpg","cyl")] 来访问两 ...

  2. formSubmit

    精简代码: <form name='form0001' method="post"> .... <li id="view"><a ...

  3. hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。

    题意:求一个无向图的,去掉两个不同的点后最多有几个连通分量. 思路:枚举每个点,假设去掉该点,然后对图求割点后连通分量数,更新最大的即可.算法相对简单,但是注意几个细节: 1:原图可能不连通. 2:有 ...

  4. 动态AdvStringGrid完美示例 (AdvStringGrid使用技巧/Cells)

    http://www.cnblogs.com/JackSun/archive/2010/12/16/1908104.html 此窗体,只需要简单准备如下,即可运行:    1,添加一个TAdvStri ...

  5. Netty构建游戏服务器(三)--netty spring简单整合

    一,基本方法 上节实现了netty的基本连接,这节加入spring来管理netty,由spring来开启netty服务. 在netty服务器中,我们建立了三个类:HelloServer(程序主入口) ...

  6. Python 和 Elasticsearch 构建简易搜索

    Python 和 Elasticsearch 构建简易搜索 作者:白宁超 2019年5月24日17:22:41 导读:件开发最大的麻烦事之一就是环境配置,操作系统设置,各种库和组件的安装.只有它们都正 ...

  7. Google的JSON风格指南

    官网:https://google.github.io/styleguide/jsoncstyleguide.xml 中文版:https://github.com/darcyliu/google-st ...

  8. android中MVC,MVP和MVVM三种模式详解析

    我们都知道,Android本身就采用了MVC模式,model层数据源层我们就不说了,至于view层即通过xml来体现,而 controller层的角色一般是由activity来担当的.虽然我们项目用到 ...

  9. centos下开启htaccess

    不知道原本 centOS是否默认支持 .htaccess 可能是因为我总弄配置文件无意中给搞坏了 今天要用到就查了下怎么开启 想要顺利开启需注意以下几点, 这几点都是在httpd.conf 这个配置文 ...

  10. 【Nutch基础教程之七】Nutch的2种执行模式:local及deploy

    在对nutch源码执行ant runtime后,会创建一个runtime的文件夹.在runtime文件夹下有deploy和local 2个文件夹. [jediael@jediael runtime]$ ...