You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java应用抛出Too many open files异常,求排查解决

解决"Too many open files"异常:排查资源泄漏点

让我梳理下你的问题:你用了try-with-resources来处理文件写入,理论上应该自动关闭流,但还是触发了java.io.FileNotFoundException: /file/path (Too many open files),而且调整文件写入逻辑(替换流、创建新实例)都没用,处理恰好5016个文件后就出问题。结合你提供的API代码,问题根本不在文件写入部分,而是HTTP请求的资源泄漏导致的文件句柄耗尽。

问题根源分析

1. 未处理HTTP错误响应的错误流

当HttpURLConnection返回非200的状态码时,系统会打开一个错误流(connection.getErrorStream())来返回错误信息。如果你不读取并关闭这个流,对应的连接资源(包括底层的文件句柄)不会被释放,随着请求次数增加,句柄会被耗尽。你之前的代码只在响应成功时处理了输入流,错误情况完全忽略了这一点。

2. 多余的手动close()调用(虽不直接导致泄漏,但属于不良实践)

在handleResponse的try-with-resources块里,你手动调用了reader.close()和in.close()——这完全没必要,try-with-resources会自动关闭实现了AutoCloseable的资源,重复关闭可能引发不必要的异常,干扰资源释放逻辑。

修复方案

修改你的handleResponse方法,确保无论请求成功还是失败,都正确处理所有流资源:

private static CoreEntity[] handleResponse(CoreEntity[] resultList, HttpURLConnection connection) throws IOException {
    final int status = connection.getResponseCode();
    InputStream inputStream = null;
    try {
        // 根据响应状态获取对应的输入流(成功流或错误流)
        inputStream = (status == HttpURLConnection.HTTP_OK) ? 
            connection.getInputStream() : connection.getErrorStream();
        
        if (inputStream != null) {
            try (InputStreamReader reader = new InputStreamReader(inputStream); 
                 BufferedReader in = new BufferedReader(reader)) {
                String inputLine;
                StringBuilder response = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                if (status == HttpURLConnection.HTTP_OK) {
                    // 成功处理逻辑
                    JSONArray jsonArray = getJSONAsArray(response.toString());
                    resultList = (CoreEntity[]) Array.newInstance(resultList.getClass().getComponentType(), jsonArray.length());
                    for (int i = 0; i < jsonArray.length(); i++) 
                        resultList[i] = (CoreEntity) GSON.fromJson(jsonArray.get(i).toString(), resultList.getClass().getComponentType());
                } else {
                    // 可选:打印错误响应内容,方便调试
                    System.out.println("Request failed with code " + status + ", response: " + response.toString());
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("Request failed with error code: " + status + ", no response stream available");
        }
    } finally {
        // 确保输入流被彻底关闭
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 断开连接,释放底层资源
        connection.disconnect();
    }
    return resultList;
}

额外验证步骤

  • 可以用系统工具排查进程的打开文件句柄:Linux下用lsof -p <你的进程ID>,Windows下用Process Explorer,看看修复后句柄数量是否不再持续增长
  • 检查getJSONAsArray方法,确保它没有打开额外的资源(比如文件、流)却未关闭

为什么之前的文件写入调整无效?

因为你的文件写入代码本身是正确的——try-with-resources已经自动关闭了FileOutputStream,你替换流、创建新DataFileWriter实例的操作都是针对没有问题的部分,自然无法解决HTTP请求导致的句柄泄漏。

内容的提问来源于stack exchange,提问作者user1830414

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:38:00