天天看點

Too many open files問題

Too many open files問題

在做項目中,遇到這樣一個問題Too many open files:

01-15 23:35:56.481 W/System.err(18683): java.io.FileNotFoundException: /data/data/xxx/C2BD95DBA8137A69CAE53D3B34886395: open failed: EMFILE (Too many open files)

01-15 23:35:56.483 W/System.err(18683): 	at libcore.io.IoBridge.open(IoBridge.java:416)

01-15 23:35:56.483 W/System.err(18683): 	at java.io.FileInputStream.<init>(FileInputStream.java:78)

01-15 23:35:56.483 W/System.err(18683): 	at java.io.FileReader.<init>(FileReader.java:42)

**01-15 23:35:56.487 W/System.err(18683): Caused by: libcore.io.ErrnoException: open failed: EMFILE (Too many open files)**

01-15 23:35:56.488 W/System.err(18683): 	at libcore.io.Posix.open(Native Method)

01-15 23:35:56.489 W/System.err(18683): 	at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)

01-15 23:35:56.489 W/System.err(18683): 	at libcore.io.IoBridge.open(IoBridge.java:400)
           

提示說檔案打開數量過多了。由于打開額檔案過多,超出系統的最高限度,核心不再讓其打開檔案了。是以再打開任何檔案就是失敗的。

後續通路檔案、socket連接配接請求等都會出現很多異常。如出現以下異常(Caused by: android.os.TransactionTooLargeException:可能原因之一就是打開檔案過多):

01-16 06:01:52.077 E/CrashHandler(32551): FATAL EXCEPTION:

01-16 06:01:52.077 E/CrashHandler(32551): java.lang.RuntimeException: Adding window failed

01-16 06:01:52.077 E/CrashHandler(32551): at android.view.ViewRootImpl.setView(ViewRootImpl.java:545)

01-16 06:01:52.077 E/CrashHandler(32551): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246)

01-16 06:01:52.077 E/CrashHandler(32551): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)

01-16 06:01:52.077 E/CrashHandler(32551): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2806)

01-16 06:01:52.077 E/CrashHandler(32551): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)

01-16 06:01:52.077 E/CrashHandler(32551): at android.app.ActivityThread.access$600(ActivityThread.java:141)

01-16 06:01:52.077 E/CrashHandler(32551): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)

01-16 06:01:52.077 E/CrashHandler(32551): at android.os.Handler.dispatchMessage(Handler.java:99)

01-16 06:01:52.077 E/CrashHandler(32551): at android.os.Looper.loop(Looper.java:137)

01-16 06:01:52.077 E/CrashHandler(32551): at android.app.ActivityThread.main(ActivityThread.java:5041)

01-16 06:01:52.077 E/CrashHandler(32551): at java.lang.reflect.Method.invokeNative(Native Method)

01-16 06:01:52.077 E/CrashHandler(32551): at java.lang.reflect.Method.invoke(Method.java:511)

01-16 06:01:52.077 E/CrashHandler(32551): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)

01-16 06:01:52.077 E/CrashHandler(32551): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)

01-16 06:01:52.077 E/CrashHandler(32551): at dalvik.system.NativeStart.main(Native Method)

**01-16 06:01:52.077 E/CrashHandler(32551): Caused by: android.os.TransactionTooLargeException**

01-16 06:01:52.077 E/CrashHandler(32551): at android.os.BinderProxy.transact(Native Method)

01-16 06:01:52.077 E/CrashHandler(32551): at android.view.IWindowSession$Stub$Proxy.addToDisplay(IWindowSession.java:664)

01-16 06:01:52.077 E/CrashHandler(32551): at android.view.ViewRootImpl.setView(ViewRootImpl.java:534)
           

以及檔案不能打開的異常(Failed to open database ):

01-16 07:28:32.140 E/SQLiteDatabase( 5954): Failed to open database '/data/data/com.demo.test/databases/ua.db'.

01-16 07:28:32.140 E/SQLiteDatabase( 5954): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database

01-16 07:28:32.140 E/SQLiteDatabase( 5954): at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)

01-16 07:28:32.140 E/SQLiteDatabase( 5954): at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
           

這些異常都有可能是檔案打開過多引起的。

那怎麼知道檔案數量究竟打開了多少呢?系統的額度是多少呢?

下面就來看一下(也是遇到了問題,才曉得這樣看)

檢視系統對打開檔案數量的限制

首先進入adb shell環境:

#cat /proc/sys/fs/file-max

Too many open files問題

輸出為86721,即整個系統限制數量。

檢視整個系統已經打開檔案數量

#cat /proc/sys/fs/file-nr

Too many open files問題

第一列就是整個系統一共打開的數量

檢視單個程序的打開檔案數量限制

#ulimit -n

Too many open files問題

由此可以看到限制是1024個。如果超出了就要抛異常了。

檢視單個程序打開了哪些檔案句柄

#ls -l /proc/26353/fd/ (26353為程序的程序id)

Too many open files問題

由上圖可以看到打開了哪些。

另外,也可以設定單個程序打開檔案的限制:

這裡設定為30。但是要root才能設定。(親自測試,設定這個後實際程序打開檔案數量大于這個數值,也還是沒有抛too many open files)。原因還不清楚。不知道是否麼有設定到核心中。)

ulimit -HSn 30

以上指令中,H指定了硬性大小,S指定了軟性大小,n表示設定單個程序最大的打開檔案句柄數量。最好不要超過4096,畢竟打開的檔案句柄數越多響應時間肯定會越慢。

Too many open files問題

怎麼會出現fd leadk洩漏?

1.檔案打開後未關閉。

2.流打開沒有關閉

3.大量socket連接配接打開沒有關閉。

4.管道、Context provider、資料庫沒有關閉, 或者資料庫連結頻繁打開忘記關閉。

是以,一定要優雅的寫代碼。

繼續閱讀