Android异常 Too many open files

当出现 Too many open files异常的时候,意味着文件句柄泄漏过多,句柄泄漏到一定数量之后(一般是接近1024)会导致程序卡死、文件读写异常、socket创建异常等。
一般来说单一进程的最大可打开文件句柄数量为1024,可通过cat proc/进程ID/limits查看。

image.png

java代码查询最大句柄数量

     public static int getMaxOpenFiles() {
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile("/proc/" + 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){
                randomAccessFile.close();
                randomAccessFile = null;
            }
        }
        return 0;
    }

当前程序已使用的句柄数量可进入文件夹 cd proc/进程ID/fd查看

image.png

当前文件句柄数量为fd目录下文件总数量,图中有88个打开的文件句柄

java代码查询当前句柄数量

    public static int getFdCount() {
        File fdFile = new File("/proc/" + Process.myPid() + "/fd");
        File[] files = fdFile.listFiles();
        return null == files ? 0 : files.length;
    }

Android中能造成文件句柄泄漏主要有以下三类

1、Process

Process process = Runtime.getRuntime().exec("getprop ");
...
process.destroy();

Process使用完之后一定要调用 destroy()

2、各种Stream

InputStream
OutputStream

ByteArrayOutputStream
ByteArrayInputStream

DataOutputStream
DataInputStream

InputStreamReader
OutputStreamWriter

BufferedInputStream
BufferedOutputStream

FileInputStream
FileOutputStream

ZipOutputStream
ZipInputStream

FileReader
FileWriter

BufferedReader
BufferedWriter

RandomAccessFile

LineNumberReader

这些用完之后一定要记得close(),养成良好的编码习惯

3、Socket

很多时候句柄泄漏是socket不能正确的关闭导致的,所以在停止业务的时候,要保证socket都能正确的关闭

通过 slof -p 进程ID 可查看当前进程的句柄情况

image.png
image.png

大致可以定位句柄泄漏的类型

你可能感兴趣的:(Android异常 Too many open files)