-3

我编写了一个 java 代码,它是组合 3 个不同软件的包装器。我正常运行代码 100,000 次。在每次运行时,应该打开、重写和关闭不同的文件,所有这些都按照正确的 try 和 catch 约定进行。如果我在 Linux 服务器上运行代码,就没有问题。但是,当我在 1000 次后的 10 秒后在我的 Mac 上运行它时,会出现打开文件过多的错误,随后在加载文件 X 和 Y 等时出错,程序终止。

我还想补充一件事:代码运行 1000 次,然后设置被更改并再次更改 1000 次,这个过程会重复。所以前 4-5 次没有问题,而在 6-7 次(意味着 6000 次运行)之后会出现此错误。

4

2 回答 2

5

最可能的解释是您的 Java 应用程序中存在导致其泄漏文件打开文件的错误。避免该问题的方法是编写代码,以便始终关闭文件句柄;例如

    // Using the 'try with resource' construct
    try (Reader r = new FileReader(...)) {
        // use the reader
    } catch (IOException ex) {
        // ...
    }

或者

    // Using classic try/catch/finally
    Reader r = null;
    try {
        r = new FileReader(...);
        // use the reader
    } catch (IOException ex) {
        // ...
    } finally {
        if (r != null) {
            try {
                r.close();
            } catch (IOException ex) {
                // ignore
            }
        }
    }

该程序可能在一个操作系统上运行,而不是在另一个操作系统上运行,因为两个系统上打开文件数量的限制不同。如果 Java GC 运行,它将关闭通过相应句柄的终结器找到的任何无法访问的文件句柄。但是,这可能不会及时发生,以防止“打开的文件过多”异常。


如果您的应用程序实际上需要同时打开大量文件,则需要取消限制。这最好使用ulimit内置的 shell 来完成,假设您使用的是基于 UNIX 的操作系统。

但是请注意,仍然会有一个无法超过的硬限制。我相信这也适用于 Windows。

于 2012-12-04T15:53:28.707 回答
4

您要么需要增加允许使用 ulimit 处理的文件数量的限制,例如

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 71679
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 2048
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 71679
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

此机器上的默认打开文件限制为 2048。在另一台机器上,限制设置为 364076 ;)

或者您必须减少使用量。这不是 Java 控制的东西,这是你必须控制的东西。

于 2012-12-04T15:53:25.057 回答