1.分析安卓源码可知,该错误是因为app同时打开的文件过多导致,安卓系统默认同时打开文件数量最多为 1024个,可以通过以下命令查看:
ulimit -a
得到结果:
-t: time(cpu-seconds) unlimited
-f: file(blocks) unlimited
-c: coredump(blocks) 0
-d: data(KiB) unlimited
-s: stack(KiB) 8192
-l: lockedmem(KiB) 64
-n: nofiles(descriptors) 1024
-p: processes 3711
-i: sigpending 3711
-q: msgqueue(bytes) 819200
-e: maxnice 40
-r: maxrtprio 0
-m: resident-set(KiB) unlimited
-v: address-space(KiB) unlimited
2.也可以用以下函数打印出当前系统配置的同时打开文件数量的最大值:
public static int getMaxOpenFiles() {
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile("/proc/" + android.os.Process.myPid() + "/limits", "r");
String line;
while ((line = randomAccessFile.readLine()) != null) {
if (line.contains("Max open files")) {
line = line.replace("Max open files", "")
.replace("files", "").trim();
String[] split = line.split(" ");
for (String item : split) {
if (!TextUtils.isEmpty(item)) {
randomAccessFile.close();
randomAccessFile = null;
return Integer.parseInt(item);
}
}
}
}
} catch (Exception e) {
// Log.w(TAG, e);
} finally {
if(randomAccessFile != null){
try {
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
randomAccessFile = null;
}
}
return 0;
}
3.查看当前已经打开的文件数量:通过 /proc/(进程号)/fd 查看,也可以通过以下函数查看。如果数量随程序运行异常增加,则需要进一步排查由哪个模块导致的。
public static int getFdCount() {
File fdFile = new File("/proc/" + android.os.Process.myPid() + "/fd");
File[] files = fdFile.listFiles();
return null == files ? 0 : files.length;
}
4.如果是socket忘记关闭,会打印出这种日志
0 lrwx------ 1 system system 64 2020-07-13 15:06 87 -> socket:[251044]
socket后面的数字可以通过 cat /proc/net/tcp 或cat /proc/net/udp 或cat /proc/进程号/net/tcp或cat /proc/进程号/net/udp找到 。找到后是数据类似这样,其中7258B276:1F9A为远程ip地址和端口:118.178.88.114:8090
434: 6600A8C0:8148 7258B276:1F9A 08 00000000:00000001 00:00000000 00000000 1000 0 58044 1 0000000000000000 28 3 30 10 -1
5.根据以上内容,可以大致定位到什么没关闭导致的该问题,进一步分析自己写的代码排查即可。