在OSX上,Java文件限制比bash中的低。

5

我已经增加了我的MacBook Pro上的最大文件限制,以便Elasticsearch可以处理更多的文件,但是它并没有起作用。

我运行了命令“ulimit -a”,它说“打开文件”的数量是100,000。我可以运行像这样的简单shell脚本:

export counter=0
while (true) ; do touch "/tmp/foo${counter}" ; export counter=`expr $counter + 1` ; done

我可以创建大量文件(在杀死脚本之前超过60,000个)。

然而,当使用Java代码在“/tmp”目录的空子目录中创建RandomAccessFiles时,我只能创建10,232个文件,然后就会出现java.io.FileNotFoundException(打开的文件太多)错误。这是我的Java代码:

import java.io.*;
import java.util.*;

public class max_open_files {
    public static void main(String ... args) throws Exception {
        File testDir = new File("/tmp/tempsubdir");
        testDir.mkdirs();

        List<File> files = new LinkedList<File>();
        List<RandomAccessFile> fileHandles = new LinkedList<RandomAccessFile>();

        try {
            while (true) {
                File f = new File(testDir, "tmp" + fileHandles.size());
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
                files.add(f);
                fileHandles.add(raf);
            }
        } catch (Exception ex) {
            System.out.println(ex.getClass() + " " + ex.getMessage());
        }

        for (RandomAccessFile raf : fileHandles) raf.close()

        for (File f : files) f.delete();

        System.out.println("max open files: " + fileHandles.size());
    }
}

这段java代码类似于Elasticsearch中的代码,用于测试文件数量(在FileSystemUtils类的maxOpenFiles方法中)。因此,Elasticsearch面临与我的Java程序相同的问题。
为什么shell脚本可以创建比Java代码(我的和Elasticsearch的)更多的文件?为什么高文件数系统限制不能被Java代码识别?
更新5月13日下午4:50:我创建了一个C版本的测试程序,以查看是否Java特定,并且似乎是这样。下面的C版本可以打开32,765个文件,而Java代码仅限于10,232个文件。
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv) {
    char name[100];
    FILE *fp;
    int ndx;

    for (ndx = 0; ndx < 50000; ndx++) {
        sprintf(name, "/tmp/foo%d.txt", ndx);
        fp = fopen(name, "w");
        if (fp == NULL) {
            fprintf(stdout, "Can not create file %d\n", ndx);
            return 1;
        }
        fprintf(fp, "hello %d", ndx);
    }

    return 0;
}
2个回答

14

Mac的Java虚拟机选项参考

-XX:- MaxFDLimit

指示虚拟机不要将文件描述符限制设置为默认最大值。默认行为是将限制设置为OPEN_MAX指定的值,该值为10240。通常情况下,这是进程可以打开的最大文件数。但是,可以使用sysctl实用程序将此限制增加到用户指定的值。在这种情况下,您可能希望传递-XX:-MaxFDLimit以阻止Java虚拟机限制打开文件的数量为10240。


3
这在我使用OpenJDK 11上似乎不起作用。有人知道这个标志是否已更改吗?文档有点难找。 - jhyot

4
在bash脚本中,你不会打开文件,只是创建它们,并在之后消除对它们的引用。而在Java版本中,似乎你保留了对它的引用,因此打开的文件数量增加了。顺便说一下,我现在意识到这并没有真正回答为什么Java只能有10,000个(+VM文件),而不是100,000个...

为什么这个回答会被投票两次(再加上我不小心点了一次赞),当回答者自己说“我现在意识到,这并没有真正回答Java为什么只能有10,000个(+VM文件)的事实”。找到一个真正的答案会很好。 - allen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接