jvm - jvm 如何以及何时何地更改 Linux 的最大打开文件值?

标签 jvm ulimit

在linux中,每个登录用户的每个进程的最大打开文件数有限制,如下:

$ ulimit -n
1024

当我学习java nio时,我想检查这个值。因为channel在Linux中也是一个文件,所以我编写了一个客户端代码来不断创建socketChannel,直到抛出以下异常:

java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:423)
at sun.nio.ch.Net.socket(Net.java:416)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:104)
at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
at java.nio.channels.SocketChannel.open(SocketChannel.java:142)

但是我发现直到创建了大约4085个socketChannel,它才会抛出这个异常。这个数字超过了1024。有人告诉我jvm隐式改变了这个值。我编写了一个java程序来执行ulimit命令,发现jvm确实改变了该值。如下:

    String [] cmdArray = {"sh","-c","ulimit -n"};
    Process p = Runtime.getRuntime().exec(cmdArray);
    BufferedInputStream in = new BufferedInputStream(p.getInputStream());
    byte[] buf = new byte[1024];
    int len = in.read(buf);
    System.out.println(new String(buf, 0, len)); //4096

有人知道 jvm 何时何地以及如何更改此值吗?是否存在一些系统日志来记录此更改或某些系统工具可以监视此更改?

最佳答案

$ strace -f -o HelloWorld.strace java HelloWorld
Hello World!
$ vi HelloWorld.strace
...
16341 getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=4*1024}) = 0
16341 setrlimit(RLIMIT_NOFILE, {rlim_cur=4*1024, rlim_max=4*1024}) = 0
...

下载openjdk,然后cd到热点目录,

$ grep -r setrlimit
...
src/os/linux/vm/os_linux.cpp:      status = setrlimit(RLIMIT_NOFILE, &nbr_files);
...

$ vi src/os/linux/vm/os_linux.cpp 
...
  if (MaxFDLimit) {
    // set the number of file descriptors to max. print out error
    // if getrlimit/setrlimit fails but continue regardless.
    struct rlimit nbr_files;
    int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
    if (status != 0) {
      if (PrintMiscellaneous && (Verbose || WizardMode))
        perror("os::init_2 getrlimit failed");
    } else {
      nbr_files.rlim_cur = nbr_files.rlim_max;
      status = setrlimit(RLIMIT_NOFILE, &nbr_files);
      if (status != 0) {
        if (PrintMiscellaneous && (Verbose || WizardMode))
          perror("os::init_2 setrlimit failed");
      }
    }
...

如果你修改上面的代码,例如

//nbr_files.rlim_cur = nbr_files.rlim_max;
nbr_files.rlim_cur = 2048;

然后重建这个openjdk,然后使用这个新的jdk执行上面的代码,你会发现输出是2048。

关于jvm - jvm 如何以及何时何地更改 Linux 的最大打开文件值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30487284/

相关文章:

java - 当编译后的代码加载到 DVM 中时,DVM 如何管理内存?

scala - IntelliJ 增加 Scalatest 堆空间

linux - 为什么 ulimit 不能成功限制常驻内存,如何限制?

linux - ulimit - help 和 man bash 提到的不同选项

linux - ulimit 命令的单独(二进制)实现?

java - Java应用程序的Supervisord和ulimit

java - 如何更改 p.getProperty 的返回值 ("os.arch");

没有显式调用的方法的 Java 堆栈框架(调用站点)

java - visualvm 配置文件 jvm 堆发现 int 数组占用大量内存

linux - bash fork error (Resource temporary unavailable) 不会停止,每次我尝试终止/重启时都会出现