Java 打开的文件太多错误,但lsof显示了合法数量的打开文件

Java 打开的文件太多错误,但lsof显示了合法数量的打开文件,java,linux,Java,Linux,我的Java程序失败了 Caused by: java.io.IOException: Too many open files at java.io.UnixFileSystem.createFileExclusively(Native Method) at java.io.File.createNewFile(File.java:883)... 以下是/etc/security/limits.conf中的关键行。他们将用户的最大文件数设置为500k: root

我的Java程序失败了

Caused by: java.io.IOException: Too many open files
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:883)...
以下是
/etc/security/limits.conf
中的关键行。他们将用户的最大文件数设置为500k:

root                     soft    nofile          500000
root                     hard    nofile          500000
*                        soft    nofile          500000
*                        hard    nofile          500000
我运行了
lsof
来计算打开的文件数量——包括全局打开的文件和jvm进程打开的文件。我检查了
/proc/sys/fs
中的计数器。一切似乎都很好。我的进程只有4301个打开的文件,限制为500k:

:~# lsof | wc -l
5526
:~# lsof -uusername | wc -l
4301
:~# cat /proc/sys/fs/file-max
744363
:~# cat /proc/sys/fs/file-max
744363
:~# cat /proc/sys/fs/file-nr
4736    0       744363
这是一个Ubuntu 11.04服务器。我甚至已经重新启动,所以我确信这些参数正在被使用

我不知道这是否相关,但该过程是由upstart脚本启动的,该脚本使用setuidgid启动该过程,如下所示:

exec setuidgid username java $JAVA_OPTS -jar myprogram.jar

我缺少什么?

我在服务器创建脚本的顶部有一段bash:

# Jack up the max number of open file descriptors at the kernel
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
invoke-rc.d procps start

# Increase max open file descriptors for this process
ulimit -n 1000000

# And for future ones as well
cat >> /etc/profile <<LIMITS
ulimit -n 1000000
LIMITS
cat >> /etc/security/limits.conf <<LIMITS
root - nofile 1000000
LIMITS
#在内核中最大数量的打开文件描述符
echo“fs.file-max=1000000”>>/etc/sysctl.conf
调用rc.d procps start
#增加此进程的最大打开文件描述符数
ulimit-n 1000000
#对未来的也一样

cat>/etc/profile/etc/security/limits.conf事实证明,问题在于我的程序是以upstart init脚本的形式运行的,
exec
节没有调用shell
ulimit
和limits.conf中的设置仅适用于shell中的用户进程

我通过将exec节更改为

exec sudo -u username java $JAVA_OPTS -jar program.jar
它在用户名的默认shell中运行java。这使得程序可以根据需要使用任意多的打开文件

我建议您也可以在调用命令之前调用
ulimit-n
;对于一个新贵脚本,我想您应该使用
脚本


我发现比
lsof
更好的诊断方法是
ls/proc/{pid}/fd|wc-l
,以获得打开文件描述符的精确计数。通过监控,我可以看到故障发生在4096个打开的fds上。我不知道4096是从哪里来的;它不在/etc的任何地方;我想这是编译到内核中的。

尝试更新堆空间并为其提供更大的最大值。不确定这两者之间为什么会有关联,但我遇到了无数不同的错误。很有趣,谢谢。但是它已经是-Xmx5800m:)在进程树中的某些地方,您正在使用ulimit设置新的限制?