天天看點

android中讀檔案流的關閉

問題描述:

在開發imonitor工具時,遇到一個很嚴重的問題,在某些機型上運作實時監控時,會在打開監控後幾秒鐘就FC了,log顯示異常為:

11-22 10:48:56.467 W/System.err(  557): java.io.IOException: Error running exec(). Command: [sh, -c, cat /sys/class/power_supply/battery/status] Working Directory: null Environment: null
11-22 10:48:56.467 D/iMonitor: CpuDataCollector(  557):  getUserUsage(): 100* ((62622 - 62482)/(2378876 - 2375017))=3
11-22 10:48:56.468 W/System.err(  557):     at java.lang.ProcessManager.exec(ProcessManager.java:211)
11-22 10:48:56.468 W/System.err(  557):     at java.lang.Runtime.exec(Runtime.java:174)
11-22 10:48:56.468 W/System.err(  557):     at java.lang.Runtime.exec(Runtime.java:129)
11-22 10:48:56.468 W/System.err(  557):     at com.sprd.tool.d.a.a(Unknown Source)
11-22 10:48:56.468 W/System.err(  557):     at com.sprd.tool.c.h.c(Unknown Source)
11-22 10:48:56.468 W/System.err(  557):     at com.sprd.tool.c.b.run(Unknown Source)
11-22 10:48:56.468 W/System.err(  557):     at java.util.Timer$TimerImpl.run(Timer.java:284)
11-22 10:48:56.468 W/System.err(  557): Caused by: java.io.IOException: Too many open files
11-22 10:48:56.469 W/System.err(  557):     at java.lang.ProcessManager.exec(Native Method)
11-22 10:48:56.469 W/System.err(  557):     at java.lang.ProcessManager.exec(ProcessManager.java:209)
11-22 10:48:56.469 W/System.err(  557):     ... 6 more           

問題分析:

由于在打開監控時,會每秒大量cat讀取手機中的系統參數檔案,導緻too many open files異常。通過 cat /proc/sys/fs/file-max可以檢視系統允許打開的最大句柄數,但終歸是有個極限的,随着時間推移,打開的檔案數一定會達到上限而發生異常,最正确的解決方案是每讀一次檔案就關一個檔案。

解決方案:

try {
            proc = runtime.exec(args);
            InputStream inputstream = proc.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(
                    inputstream);
            bufferedreader = new BufferedReader(inputstreamreader);
            // read the ls output
            String line = "";
            sb = new StringBuilder(line);
            while ((line = bufferedreader.readLine()) != null) {
                ...
            }
            if (proc.waitFor() != 0) {
                Log.d(TAG, "exit value = " + proc.exitValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (bufferedreader != null) {
                try {
                    bufferedreader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }           

對于

new BufferReader(new InputStreamReader(new InputStream(...)));

這種多層次的流調用,隻需對最外層執行close(),外層的會依次關閉裡層的。

下一篇: 第二周進度