隨筆 - 1, 文章 - 0, 評論 - 10, 引用 - 0
          數(shù)據(jù)加載中……

          經(jīng)典的IO代碼為什么有資源泄漏?

          最近在開發(fā)中,使用到IO操作進行反序列化操作,使用了在各種資料中常見的關(guān)于IO操作的經(jīng)典代碼,在自測和測試人員的測試中都沒有發(fā)現(xiàn)任何問題!
          代碼如下

          public ?Object?readObject(File?file)
          ????{
          ????????Object?o?
          = ? null ;
          ????????
          if ?(file.exists())
          ????????{
          ????????????ObjectInputStream?ois?
          = ? null ;
          ????????????
          try
          ????????????{
          ????????????????ois?
          = ? new ?ObjectInputStream( new ?FileInputStream(file));
          ????????????????o?
          = ?ois.readObject();
          ????????????}
          ????????????
          catch ?(Throwable?e)
          ????????????{
          ????????????????e.printStackTrace();
          ????????????}
          ????????????
          finally
          ????????????{
          ????????????????
          if ?(ois? != ? null )
          ????????????????{
          ????????????????????
          try
          ????????????????????{
          ????????????????????????ois.close();
          ????????????????????}
          ????????????????????
          catch ?(IOException?e)
          ????????????????????{
          ????????????????????????e.printStackTrace();
          ????????????????????}
          ????????????????}
          ????????????}????????????
          ????????}
          ????????
          return ?o;
          ????}

          忽然一天測試人員聯(lián)系我說這部分代碼導(dǎo)致系統(tǒng)無法啟動,原因僅僅是因為讓該部分代碼不斷的處理一個為序列化文件!
          我仔細(xì)分析一下代碼,沒有問題呀,反序列化失敗就直接關(guān)閉了ois對象,不可能造成資源泄漏,于是用單步跟蹤的方式
          查看處理非法文件的詳細(xì)情況:
          1、創(chuàng)建FileInputStream 沒有問題
          2、創(chuàng)建ObjectInputStream失敗 沒有問題
          3、進入catch塊,打印堆棧 沒有問題
          4、進入finnaly塊,if (ois != null)為false,這時意識到出問題了
          原來創(chuàng)建FileInputStream成功,此時已經(jīng)申請了資源,但在后續(xù)創(chuàng)建ObjectInputStream時失敗,但此時又沒有保存FileInputStream
          的引用,無法釋放資源,最終導(dǎo)致了資源泄漏??磥碓谝院蟮?font color="#0000ff">IO的編程中一定要保存基本流的引用,否則在類似上面的情況
          在轉(zhuǎn)換流失敗后,無法安全的釋放資源!
          下面為修改后的代碼:

          ?public?Object?readObject(File?file)
          ????{
          ????????Object?o?
          =?null;
          ????????
          if?(file.exists())
          ????????{
          ????????????FileInputStream?fis?
          =?null;
          ????????????ObjectInputStream?ois?
          =?null;
          ????????????
          try
          ????????????{
          ????????????????fis?
          =?new?FileInputStream(file);
          ????????????????ois?
          =?new?ObjectInputStream(fis);
          ????????????????o?
          =?ois.readObject();
          ????????????}
          ????????????
          catch?(Throwable?e)
          ????????????{
          ????????????????e.printStackTrace();
          ????????????}
          ????????????
          finally
          ????????????{
          ????????????????
          if?(fis?!=?null)
          ????????????????{
          ????????????????????
          try
          ????????????????????{
          ????????????????????????fis.close();
          ????????????????????}
          ????????????????????
          catch?(IOException?e)
          ????????????????????{
          ????????????????????????e.printStackTrace();
          ????????????????????}
          ????????????????}
          ????????????}????????????
          ????????}
          ????????
          return?o;
          ????}


          posted on 2006-03-24 21:47 mooninwell 閱讀(1388) 評論(10)  編輯  收藏 所屬分類: Java原創(chuàng)

          評論

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          有一點疑問:
          在文件存在的情況下,在什么情況下會出現(xiàn)fis創(chuàng)建成功而ois創(chuàng)建失敗?
          另:finally下還是要加上關(guān)閉ois的為好。
          2006-03-25 09:14 | 阿偉的技術(shù)小巢

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          收到,謝謝分享
          2006-03-25 10:30 | flyfoxs

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          頻繁調(diào)用這個方法OPEN/CLOSE STREAM也不是一個好的做法吧?如果一直使用一個ObjectInputStream/ObjectOutputStream就要小心內(nèi)存泄漏。
          2006-03-25 12:03 | 非魚

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          只要文件存在并且讀的權(quán)限就可以成功創(chuàng)建fis,但將fis轉(zhuǎn)換為ois則文件必需滿足序列化的文件格式。至于ois的關(guān)閉,從理論上關(guān)閉了基本流fis就不會存在泄漏,而且在實際測試中,window、solaris、aix系統(tǒng)下都沒有問題@阿偉的技術(shù)小巢
          2006-03-25 20:37 | mooninwell

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          資源和io流是一一對應(yīng)的,而且良好的編程習(xí)慣應(yīng)該是對獨占資源應(yīng)該盡快的釋放,因此處理邏輯應(yīng)該和從資源中獲取信息相分離@非魚
          2006-03-25 20:40 | mooninwell

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          @mooninwell

          因OIS/OOS使用HANDLETABLE保存被序列化對象的引用,實踐中應(yīng)注意調(diào)用OOS.reset()方法,否則在大量對象序列化時會發(fā)生ML。
          2006-03-25 21:44 | 非魚

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          @非魚
          以前工作很少用到IO,特別是序列化部分!今天在你的提醒下,看了一下oos的實現(xiàn),發(fā)現(xiàn)一直使用一個oos/ois的確存在ML的可能性,但我認(rèn)為這中使用情況在實際應(yīng)用中很少發(fā)生。另:發(fā)現(xiàn)OOS的close方法內(nèi)也包含了reset方法的實現(xiàn),但ois沒有實現(xiàn)reset方法,會拋異常。
          2006-03-26 00:45 | mooninwell

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          用InputStream代替File作為參數(shù)豈不更好?
          2006-03-27 09:49 | hubeicaolei

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          同意樓上的
          2006-03-27 10:07 | nkoffee

          # re: 經(jīng)典的IO代碼為什么有資源泄漏?  回復(fù)  更多評論   

          @mooninwell

          OIS沒有實現(xiàn)reset()方法,是因為它從INPUT流中讀取TC_RESET標(biāo)志來RESET HANDLE TABLE。這樣可以保證通過網(wǎng)絡(luò)SERIALIZATION時不出問題。
          2006-03-28 00:01 | 非魚

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 乐亭县| 南平市| 大城县| 虎林市| 永福县| 南漳县| 商水县| 安溪县| 增城市| 梁山县| 浑源县| 景宁| 郴州市| 林甸县| 绵阳市| 明水县| 浦北县| 乌鲁木齐县| 洛川县| 光山县| 玉林市| 苗栗县| 安仁县| 广元市| 宝兴县| 景泰县| 峡江县| 双牌县| 阳新县| 玛纳斯县| 敖汉旗| 木兰县| 白城市| 正蓝旗| 泊头市| 南江县| 民县| 阳城县| 中西区| 东方市| 鸡泽县|