gpt4 book ai didi

java - 打开的文件太多错误

转载 作者:行者123 更新时间:2023-11-29 08:04:33 27 4
gpt4 key购买 nike

简介

我在网上找到了很多关于Too many open files异常的信息,但我无法解决这个奇怪的案例。正如我所读到的,当超过操作系统中定义的进程打开的文件描述符的数量时,将抛出异常。这些文件的性质多种多样。文件可以是套接字、文档等。我已经找到了在我的 Java 应用程序中实现的可靠且安全的文件打开方式。

该应用程序是一个使用Boilerpipe 下载网页的短程序。算法。这样我就得到了那个站点最有代表性的内容。然后,我将其以适当的格式(TREC 格式)写入磁盘。这些网站的 URL 取 self 使用 JDBC 连接器 访问的 MySQL 数据库。

所以,我认为可以从三个不同的地方抛出异常:

  • 连接到数据库
  • HTTP 连接到网站
  • 打开和写入文件

尽管如我所说,我认为我使用正确的方式打开和写入这些文件。

问题

有数以千计的 URL 需要处理,一段时间后会抛出异常(是什么让它也很难调试...)。我不知道这是否重要,但 URL 分为不同的类别,我运行程序的不同实例以加快整个过程。类别不重叠,因此应该没有任何问题。

代码

为了使其更具可读性,我将仅展示简化的代码的这三个部分:

  1. 数据库访问

    // Connect to database
    Connection dbconn = null;

    try {
    String dbUrl = "jdbc:mysql://" + dbServer + "/" + dbName;
    Class.forName ("com.mysql.jdbc.Driver").newInstance ();
    dbconn = DriverManager.getConnection(dbUrl, dbUser, dbPass);
    System.out.println ("Database connection established");
    } catch (Exception e) {
    e.printStackTrace();
    System.err.println ("Cannot connect to database server");
    System.exit(-1);
    }

    System.out.println(" Downloading category: " + category);

    Statement s = null;
    try {
    s = dbconn.createStatement();
    } catch (SQLException e) {
    System.err.println ("Error on creating the statement");
    System.exit(-1);
    e.printStackTrace();
    }

    String q = "SELECT resource,topic FROM " +
    "content_links " +
    "WHERE topic LIKE 'Top/" + category + "%';";

    try {
    s.executeQuery(q);
    } catch(Exception e) {
    System.err.println ("Error on executing the SQL statement");
    System.exit(-1);
    e.printStackTrace();
    }

    ResultSet rs = null;
    try {
    rs = s.getResultSet ();
    } catch (SQLException e) {
    System.err.println ("Error on getting the result set");
    System.exit(-1);
    e.printStackTrace();
    }


    int count = 0, webError = 0;

    // work with the result set
    try {
    while (rs.next ()) {

    // MAIN LOOP
    }

    } catch (SQLException e) {
    System.err.println ("Error on getting next item");
    System.exit(-1);
    e.printStackTrace();
    }

    // Close connection to database
    if (dbconn != null) {
    try {
    dbconn.close ();
    System.out.println (" Database connection terminated");
    } catch (Exception e) { /* ignore close errors */ }
    }
  2. HTTP 连接,提取站点标题和样板过滤器

    try {

    String title = "";
    org.jsoup.nodes.Document doc = Jsoup.connect(urlVal).get();

    for (Element element : doc.select("*")) {
    if (element.tagName().equalsIgnoreCase("title")) {
    title = element.text();
    }
    if (!element.hasText() && element.isBlock()) {
    element.remove();
    }
    }

    String contents = "";
    contents = NumWordsRulesExtractor.INSTANCE.getText(doc.text());
    storeFile(id, urlVal, catVal, title, contents);
    }
    } catch (BoilerpipeProcessingException e) {
    System.err.println("Connection failed to: " + urlVal);
    } catch (MalformedURLException e1) {
    System.err.println("Malformed URL: " + urlVal);
    } catch(Exception e2) {
    System.err.println("Exception: " + e2.getMessage());
    e2.getStackTrace();
    }
  3. 写文件

    private static void storeFile(String id, String url, String cat, String title, String contents) {
    BufferedWriter out = null;
    try {
    out = new BufferedWriter(
    new OutputStreamWriter(
    new FileOutputStream(
    new File(path + "/" + id + ".webtrec")),"UTF8"));

    // write in TREC format
    out.write("...");
    } catch (IOException e) {
    System.err.println("Error: " + e.getMessage());
    e.printStackTrace();
    } finally {
    try {
    out.close();
    } catch (IOException e) {
    System.err.println("Error: " + e.getMessage());
    e.printStackTrace();
    }
    }

最佳答案

是的。您正在泄漏文件描述符。

在第一种情况下,您打开了一个数据库连接并且永远不会关闭它。连接通常会使用套接字或其他方式与数据库通信。由于您不关闭连接,因此不会关闭套接字,并且您会泄漏文件描述符。

在第二种情况下,我怀疑对 Jsoup.connect(urlVal) 的调用正在打开一个连接,您随后没有关闭该连接。这将导致文件描述符泄漏。

更正 - Connection 接口(interface)上没有 close() 方法。看起来必须创建实际连接,然后通过 get 方法在内部关闭。假设是这样,在第二种情况下不存在文件描述符泄漏。

第三种情况不泄露文件描述符。但是,如果您未能打开文件,out.close(); 语句将尝试调用 null 上的方法 ... 并将抛出 NPE。


解决办法是找到所有打开文件的地方,数据库连接,http连接,并确保句柄总是关闭。

一种方法是将 close() 调用(或等效的)放在 finally block 中......但要确保你不会不小心在 null 上调用 close()

另一种方法是使用 Java 7 的“try with resource”语法。例如:

private static void storeFile(String id, String url, String cat, 
String title, String contents) {
try (BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File(path + "/" + id + ".webtrec")),"UTF8"))) {
// write in TREC format
out.write("...");
out.close();
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}

(但请注意,Java 7 语法只能用于实现新的 Closeable 接口(interface)的资源。)

关于java - 打开的文件太多错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12139831/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com