天天看点

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、数据库没有关闭, 或者数据库链接频繁打开忘记关闭。

所以,一定要优雅的写代码。

继续阅读