<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    java nio的嚴重BUG(續)

    Posted on 2009-10-06 23:56 dennis 閱讀(3514) 評論(0)  編輯  收藏 所屬分類: javamy open-source
        上篇文章我談到了java nio的一個嚴重BUG,并且介紹了jetty是如何規避這個BUG的。我在將這部分代碼整合進yanf4j的過程中發現了不少誤判的情況,讓我們看看誤判是怎么發生的。jetty的解決方案是通過在select返回為0的情況下,計量Selector.select(timeout)執行的時間是否與傳入的timeout參數相差太大(小于timeout的一半),如果相差太大,那么認為發生一次bug,如果發生的次數超過設定值,依據嚴重程度進行處理:第一嘗試取消任何有效并且interestOps等于0的SelectionKey;第二次就是重新創建一個Selector,并將有效的Channel注冊到新的Selector。誤判的發生就產生于這個時間的計量上,看javadoc可以發現它是這樣描述這個方法的:

        This method performs a blocking selection operation. It returns only after at least one channel is selected, this selector's wakeup method is invoked, or the current thread is interrupted, whichever comes first

        意思就是說這個方法將阻塞select調用,直到下列三種情況之一發生才返回:至少一個channel被選中;同一個Selector的wakeup方法被調用;或者調用所處的當前線程被中斷。這三種情況無論誰先發生,都將導致select(timeout)返回。因此為了減少誤判,你需要將這三種情況加入判斷條件。Jetty的方案已經將select返回為0的情況考慮了,但是卻沒有考慮線程被中斷或者Selector被wakeup的情況,在jetty的運行時也許不會有這兩種情況的發生,不過我在windows上用jdk 6u7跑jetty的時候就發現了誤判的日志產生。除了wakeup和線程中斷這兩種情形外,為了進一步提高判斷效率,應該將操作系統版本和jdk版本考慮進來,如果是非linux系統直接不進行后續的判斷,如果是jdk6u4以后版本也直接忽略判斷,因此yanf4j里的實現大致如下:
                boolean seeing = false;
                
    /**
                 * 非linux系統或者超過java6u4版本,直接返回
                 
    */
                
    if (!SystemUtils.isLinuxPlatform()
                        
    || SystemUtils.isAfterJava6u4Version()) {
                    
    return seeing;
                }
                
    /**
                 * 判斷是否發生BUG的要素:
                 * (1)select返回為0
                 * (2)wait時間大于0
                 * (3)select耗時小于一定值
                 * (4)非wakeup喚醒
                 *  (5)非線程中斷引起
                 
    */
                
    if (JVMBUG_THRESHHOLD > 0 && selected == 0
                        
    && wait > JVMBUG_THRESHHOLD && now - before < wait / 4
                        
    && !this.wakenUp.get() /* waken up */
                        
    && !Thread.currentThread().isInterrupted()/* Interrupted */) {
                    
    this.jvmBug.incrementAndGet();

        其中判斷是否是線程中斷引起的是通過Thread.currentThread().isInterrupted(),判斷是否是wakeup是通過一個原子變量wakenUp,當調調用Selector.wakeup時候,這個原子變量更新為true。判斷操作系統和jdk版本是通過System.getProperty得到系統屬性做字符串處理即可。類似的代碼示例:
    public static final String OS_NAME = System.getProperty("os.name");

        
    private static boolean isLinuxPlatform = false;

        
    static {
            
    if (OS_NAME != null && OS_NAME.toLowerCase().indexOf("linux">= 0) {
                isLinuxPlatform 
    = true;
            }
        }
        
    public static final String JAVA_VERSION = System
                .getProperty(
    "java.version");
        
    private static boolean isAfterJava6u4Version = false;
        
    static {
            
    if (JAVA_VERSION != null) {
                
    // java4 or java5
                if (JAVA_VERSION.indexOf("1.4.">= 0
                        
    || JAVA_VERSION.indexOf("1.5.">= 0)
                    isAfterJava6u4Version 
    = false;
                
    // if it is java6,check sub version
                else if (JAVA_VERSION.indexOf("1.6.">= 0) {
                    
    int index = JAVA_VERSION.indexOf("_");
                    
    if (index > 0) {
                        String subVersionStr 
    = JAVA_VERSION.substring(index + 1);
                        
    if (subVersionStr != null && subVersionStr.length() > 0) {
                            
    try {
                                
    int subVersion = Integer.parseInt(subVersionStr);
                                
    if (subVersion >= 4)
                                    isAfterJava6u4Version 
    = true;
                            } 
    catch (NumberFormatException e) {

                            }
                        }
                    }
                    
    // after java6
                } else
                    isAfterJava6u4Version 
    = true;
            }
        }


    主站蜘蛛池模板: 久久久久亚洲AV综合波多野结衣 | 性短视频在线观看免费不卡流畅| 久久国产成人亚洲精品影院| 无套内谢孕妇毛片免费看看| 四虎影在线永久免费四虎地址8848aa | 亚洲一区二区三区在线播放| 国产精品亚洲一区二区无码 | 免费一级全黄少妇性色生活片 | 九月丁香婷婷亚洲综合色| 曰批全过程免费视频在线观看无码| 亚洲欧洲日产国码一级毛片| 国产va免费观看| 国产精品亚洲成在人线| 99久久精品免费精品国产| 亚洲精品国产成人| 成年女人毛片免费播放人| 亚洲国产精品成人AV在线| mm1313亚洲精品国产| 国产成人涩涩涩视频在线观看免费| 亚洲欧洲无码AV不卡在线| 免费一级成人毛片| 亚洲无砖砖区免费| 免费看韩国黄a片在线观看| 色天使色婷婷在线影院亚洲| 亚洲国产一级在线观看| 91精品成人免费国产| 亚洲区精品久久一区二区三区| 女人与禽交视频免费看| 特级毛片A级毛片100免费播放| 久久精品国产亚洲7777| 最近免费中文字幕大全免费 | 国产自偷亚洲精品页65页| 久久久久高潮毛片免费全部播放| 亚洲一区无码中文字幕乱码| 国产乱子伦精品免费女| 精品国产免费一区二区三区香蕉| 亚洲H在线播放在线观看H| 亚洲精品国产福利一二区| 51视频精品全部免费最新| 免费人成动漫在线播放r18| 4480yy私人影院亚洲|