1. 程式人生 > >Java nio的一個嚴重BUG,導致cpu 100%

Java nio的一個嚴重BUG,導致cpu 100%

這個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)中移除: 

Java程式碼:

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。

俺實際上被這個BUG害的很慘, 因為降到了jdk 6u4 CPU仍然會時不時的增高, 原因是低版本的Jetty同樣在這方面處理的不是很合理. 
    Jetty關於這個BUG的描述:http://jira.codehaus.org/browse/JETTY-937, 用JETTY做為應用, JETTY1.6.22 + JDK 6U4俺現在測下來, CPU基本正常.

另外nio還有幾個嚴重的bug,在實際執行中碰到了,sun在u18才修復,而現在u18還沒正式釋出。

http://bugs.sun.com/view_bug.do?bug_id=6693490 這個BUG,一個間接影響也是關閉的channel一直有ready事件,select不阻塞並立即返回0,也就是導致CPU 100%,同樣也是可以通過這裡描述的方案解決的。

在最新的Netty裡面使用了建立新的selector解決問題(NioEventLoop的rebuildSelector)

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

相關推薦

Java nio一個嚴重BUG導致cpu 100%

這個BUG會在Linux上導致cpu 100%,使得nio server/client不可用,具體的詳情可以看這裡http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933  。令人失望的是這個BUG直到jdk 6u4才解決,sun的拖沓讓人難以

Java nio一個嚴重BUG

  這個BUG會在linux上導致cpu 100%,使得nio server/client不可用,具體的詳情可以看這裡。令人失望的是這個BUG直到jdk 6u4才解決,sun的拖沓讓人難以相信。這個BUG在server端容易出現,因為server端有頻繁地接入斷開連線。使

java--建立一個Test類包含有一個public許可權的int型成員變數與一個char型別的成員變數觀察在main方法中的初始值。

//建立一個Test類 class Test1{ //包含有一個public許可權的int型成員變數與一個char型別的成員變數 public int a; public char c; } //主類 public class Test{ //主函式 publ

HDFS(三)——用 Java 建立一個 HDFS 目錄HDFS 的許可權的問題

一、匯入 HDFS 所需 jar 包 把解壓後的 hadoop 資料夾下的 common 目錄中的 jar,和裡面的 lib 包中所有的 jar,以及 hdfs 目錄下的 jar,和裡面的 lib 包中所有的 jar 都新增到專案的環境變數中。 二、編寫測試程式碼 im

Java 輸入一個正整數將其用中文打印出來

輸入一個正整數,將其用中文打印出來。使用java 實現 import  java.util.Scanner; public static void main(String[]  arge){          

[2015.09.01]阿里雲升級雲盾引入BUG導致誤刪使用者檔案

9月1日,阿里雲再次出現故障,有多位使用者在微博爆出執行在阿里雲上的系統命令及可執行檔案被刪除。 看看他們都遭遇了什麼: @點心哥哥:現在ECS 的機器,每執行一個命令,就完蛋一個命令,被刪除,已經嚴重影響到我們線上服務與運維了,怎麼辦? @francs3:我有臺阿里雲伺服器 more ,cat ,

java 輸入一個連結串列輸出該連結串列中倒數第k個結點。

輸入一個連結串列,輸出該連結串列中倒數第k個結點。 解題思路: 1、當輸入的連結串列為空的時候直接返回空 2、當輸入的k值大於連結串列的節點數的時候直接返回null; 3、先遍歷連結串列得出連結串列的

Java經典演算法集——如下:用1、2、2、3、4、5這六個數字java一個main函式打印出所有不同的排列如:512234、412345等要求:"4"不能在第三位"3"與"5"不能相連。

轉:http://www.blogjava.net/SongJunke/articles/101741.html 演算法程式題:     該公司筆試題就1個,要求在10分鐘內作完。     題目如下:用1、2、2、3、4、5這六個數字,用java寫一個main函式,打印出所

今天開始學Java 給定一個正整數編寫程式計算有多少對質數的和等於輸入的這個正整數並輸出結果。

給定一個正整數,編寫程式計算有多少對質數的和等於輸入的這個正整數,並輸出結果。輸入值小於1000。如,輸入為10, 程式應該輸出結果為2。(共有兩對質數的和為10,分別為(5,5),(3,7)) 輸入描述:輸入包括一個整數n,(3 ≤ n < 1000)輸出描述:輸出對

java建立一個銀行賬戶並具有存取款操作(引數傳遞)

public class BankAccount{public static void main(String[] args) {Value v1 = new Value();v1.v = 10000;Value v2 = new Value();v2.v = 3000;V

java一個學生類對總成績降序排列輸出並列印名次

import java.util.ArrayList; import java.util.Collections; import java.util.List;   public class Student implements Comparable{    

bashd程序無法殺掉導致cpu很高

背景    伺服器被當做挖礦肉雞,未知的bashd程序佔用cpu非常高,程序無法殺掉,殺掉後進程無限重啟。漏洞概述http://blog.jobbole.com/94518/解決步驟    top查詢發現bashd程序名稱佔用cpu非常高查詢程序名稱,找到執行指令碼在哪個目錄

用1、2、2、3、4、5 這六個數字java一個main 函式打印出所有不同的排列要求:"4"不能在第三位"3"與"5"不能相連。

下面的程式碼是網上找的,我按照自己的理解加的註釋: public class test01 { public static void main(String[] args) { // 理論上,題目所要求的排列組成的數字,都包含在122345~5

使用Java編寫一個http請求要求使用HttpClient

HttpClient介紹: HttpClient是Apache提供的一個用於在Java中處理HTTP請求、響應操作的工具,它比JDK中自帶的URLConnection更加靈活好用,因此越來越多的人開始使用它來實行對HTTP的請求操作。HttpClient的初級使用我是在ID

java-建立一個執行緒在控制檯不斷輸出當前時間精確到時分秒每隔一秒輸出一次。

對其實現的一個方法是:          採用繼承Thread類 重寫run方法。 import java.text.SimpleDateFormat; import java.util.Date; /** * 建立一個執行緒,在控制檯不斷輸出當前時間,精確到時分秒,

[基本演算法]Java——編寫一個線段類實現基本數學演算法

{        float f;        float d;        Point ab=new Point();        Point ac=new Point();        Point e=new Point();        ab.x=b.x-a.x;        ab.y=b.

Java給定一個字串陣列判斷每個字元出現次數

題目要求:給定一個字串,判斷每個字元出現多少次? 解決思路:利用Map的特性:即Map集合中如果兩個key(鍵)值是一樣相同的,那麼,後放(put)入的值會將前面存在的value(值)替換掉,也就是覆蓋了前面的value。 package com.zhj.www; impor

就為了一個原子操作其他CPU核心罷工了

## i++問題 “阿Q趕快回去吧,隔壁二號車間的虎子說我們改了他們的資料,上門來鬧事了” 由於老K的突然出現,我不得不提前結束與小黑的交流,趕回了CPU一號車間。 見到我回來,虎子立刻朝我嚷嚷:“你們是怎麼回事?才幾納秒的時間,就把資料給我改了,你說這事怎麼辦吧!” 我聽著迷迷糊糊的,連連說到:“虎

客戶的一個緊急bug我用了兩種方式進行 C# 反編譯修改原始碼

## 一:背景 ### 1. 講故事 週五下午運營反饋了一個緊急bug,說客戶那邊一個資訊列表打不開,急需解決,附帶的日誌檔案也發過來了,看了下日誌大概是這樣的: ``` C# 日期:2020-11-13 12:25:45,923 執行緒ID:[3924] 日誌級別:INFO 錯誤類:xxx