問題描述:
在開發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(),外層的會依次關閉裡層的。