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

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

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

    莊周夢蝶

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

    Kilim的小BUG

    Posted on 2010-11-03 23:22 dennis 閱讀(2808) 評論(2)  編輯  收藏 所屬分類: java

        我最近在實現(xiàn)一個基于Kilim的HttpClient,在處理響應body特別大的情形下遇到了kilim的一個BUG,有必要記錄下。
        問題是這樣,Kilim將連接封裝為EndPoint對象,EndPoint有個方法fill用于從管道讀數(shù)據(jù)到緩沖區(qū),并且可以指定希望至少讀到多少個字節(jié)(atLeastN)才返回。那么在進入此方法的時候會判斷緩沖區(qū)是否有足夠空間容納atLeastN個字節(jié),如果沒有,則創(chuàng)建一個更大的緩沖區(qū),并將“老”的緩沖區(qū)的數(shù)據(jù)拷貝到新緩沖區(qū),這部分代碼是這樣實現(xiàn):
    public ByteBuffer fill(ByteBuffer buf, int atleastN) throws IOException, Pausable {
            
    if (buf.remaining() < atleastN) {
                ByteBuffer newbb 
    = ByteBuffer.allocate(Math.max(buf.capacity() * 3 / 2, buf.position() + atleastN));
                buf.rewind();
                newbb.put(buf);
                buf 
    = newbb;
            }
            ……
    }

        后面的代碼我省略了,這個BUG就出現(xiàn)在這段代碼里。這段代碼的邏輯很簡單,先是創(chuàng)建一個新的更大的緩沖區(qū),然后將老的緩沖區(qū)的數(shù)據(jù)put到新的緩沖區(qū),在put之前調(diào)用rewind方法將老的緩沖區(qū)的position設置為0。查看rewind干了什么:
     public final Buffer rewind() {
        position 
    = 0;
        mark 
    = -1;
        
    return this;
        }

        僅僅是將position設置為0,并讓mark失效。position指向下一個讀或者寫的位置,這里在寫入到新緩沖區(qū)之前確實需要將position設置為0,以便寫入從老的緩沖區(qū)第一個位置開始。問題是什么?問題是position僅僅指定了下一個讀取數(shù)據(jù)的位置,卻沒有指定有效數(shù)據(jù)的大小,換句話說,沒有指定老的緩沖區(qū)的limit。因此這里造成的后果是老的緩沖區(qū)整個被寫入到新的老緩沖區(qū),包括有效數(shù)據(jù)和無效數(shù)據(jù),默認情況下緩沖區(qū)的limit等于capacity。

       這個bug可以通過下面程序看出來:
            ByteBuffer old = ByteBuffer.allocate(8);
            old.putInt(
    99);
            ByteBuffer newBuf 
    = ByteBuffer.allocate(16);
            old.rewind();
            newBuf.put(old);
            newBuf.putInt(
    100);

            newBuf.flip();
            System.out.println(newBuf.remaining());
            System.out.println(newBuf.getInt());
            System.out.println(newBuf.getInt());
            System.out.println(newBuf.getInt());

        先往old寫入一個整數(shù)99,然后創(chuàng)建newBuf并寫入old數(shù)據(jù),并再寫入一個整數(shù)100,最后從newBuf讀數(shù)據(jù)。本來我們預期只應該讀到兩個整數(shù)99和100,但是中間卻插入一個0,輸出如下:

    12
    99
    0
    100

        12表示緩沖區(qū)可讀的數(shù)據(jù),本來應該是8個字節(jié),卻多了4個字節(jié)的無效數(shù)據(jù)。

         這個BUG解決很簡單,將rewind修改為flip方法即可,flip不僅將position設置為0,也將limit設置為當前位置:
      public final Buffer flip() {
        limit 
    = position;
        position 
    = 0;
        mark 
    = -1;
        
    return this;
        }


        修改上面的測試程序,符合我們的預期了:
            ByteBuffer old = ByteBuffer.allocate(8);
            old.putInt(
    99);
            ByteBuffer newBuf 
    = ByteBuffer.allocate(16);
            old.flip();
            newBuf.put(old);
            newBuf.putInt(
    100);

            newBuf.flip();
            System.out.println(newBuf.remaining());
            System.out.println(newBuf.getInt());
            System.out.println(newBuf.getInt());;

        輸出:
    8
    99
    100

        總結,使用rewind的前提是limit已經(jīng)正確設置,例如你將buffer寫入成功并想記錄這個buffer,可以使用rewind:
    while (buffer.hasRemaining()) //發(fā)送數(shù)據(jù)
        networkChannel.write(buffer);
    buffer.rewind(); 
    // 重置buffer,準備寫入日志管道
    while (buffer.hasRemaining()) // 寫入日志
        loggerChannel.write(buffer);

       而flip用于緩沖區(qū)發(fā)送或者讀取之前,也就是將緩沖區(qū)設置為等待傳出狀態(tài)。

    評論

    # re: Kilim的小BUG  回復  更多評論   

    2010-12-14 07:30 by zz69
    這里應該注意到原始設計中 的使用場景是當oldbuffer 不夠大的時候,也就是oldbuffer有一個隱含的意思就是已被寫滿,那么limit == capacity 使用flip抑或是rewind效果是一樣的,甚至這個地方rewind更能表現(xiàn)出代碼原始的使用企圖

    個人理解,還請多多指教

    # re: Kilim的小BUG  回復  更多評論   

    2010-12-14 10:48 by dennis

    @zz69
    這里并沒有什么隱含的意思,判斷條件是
    buf.remaining() < atleastN

    而不是

    !buf.hasRemaining()
    主站蜘蛛池模板: 77777午夜亚洲| 无码色偷偷亚洲国内自拍| 黄页网站在线看免费| 亚洲国产精品无码中文lv| 亚洲AV日韩精品一区二区三区| 国产免费区在线观看十分钟| 亚洲黄色在线观看视频| 成年女人永久免费观看片| 大地资源在线资源免费观看| 一区二区亚洲精品精华液| 青青草原亚洲视频| 免费在线看v网址| 一级午夜免费视频| 亚洲国产成人久久| 国产成人亚洲综合| 在线观看日本免费a∨视频| www成人免费视频| 亚洲黄页网在线观看| 2048亚洲精品国产| 国产麻豆视频免费观看| 91在线视频免费观看| 国产成人亚洲精品| 国产AV无码专区亚洲A∨毛片| 免费视频淫片aa毛片| 久久免费区一区二区三波多野| 亚洲AV无码之国产精品| 亚洲欧洲国产日韩精品| 免费国产a国产片高清| 中文免费观看视频网站| 99视频在线免费观看| 亚洲综合精品成人| 色播亚洲视频在线观看| 国产中文在线亚洲精品官网| 最近中文字幕免费mv视频7| 久9这里精品免费视频| 九九久久精品国产免费看小说 | 亚洲黄色网站视频| 亚洲真人无码永久在线| 免费a级毛片在线观看| 无码国产精品一区二区免费I6| 无码国产精品一区二区免费16|