如何在Java中获取打开文件限制?

3
有哪些选项可以在Java中获取(硬/软)打开文件限制?
OSHI的FileSystem.getMaxFileDescriptors()方法支持获取最大打开文件描述符数量,但它提到“可能存在较低的每进程限制”,这对我来说似乎有点含糊不清。
另一种可能性是使用JNA或JNI调用getrlimit(),这应该可以获取JVM进程的打开文件限制。但我有点担心它是否能在足够多的操作系统上工作。
除了上述提到的方法外,还有其他可能性吗?

最简单的方法是提供一个命令行选项来传递您想要使用的限制。这不必是实际的进程限制,它可以是一些较低的限制以节省资源。但如果您真的需要每个进程的限制,我认为纠缠JNA调用是您唯一的选择。 - markspace
也许你想知道在同一时间内可以安全打开多少文件?这是一个不同的问题,因为除了ulimit之外可能还有其他限制。 - Lorinczy Zsigmond
我主要关注进程可以打开的TCP连接的最大打开文件数,我已经了解了其他相关限制,比如最大端口等。 - stackseti
1个回答

3

Linux在/proc/sys/fs中提供以下值:

file-max和file-nr,file-max的值表示Linux内核将分配的最大文件句柄数。当您收到大量有关文件句柄不足的错误消息时,可能需要增加此限制。

nr_open 表示进程可以分配的最大文件句柄数。默认值是1024*1024(1048576),对于大多数机器来说,这应该足够了。实际限制取决于RLIMIT_NOFILE资源限制。

MacOS通过sysctl提供以下值:

kern.maxfiles: 245760
kern.maxfilesperproc: 122880
kern.num_files: 8685

FreeBSD 也通过 sysctl 提供这些信息,但对于打开的文件有不同的名称。

kern.maxfiles: 64534
kern.maxfilesperproc: 58077
kern.openfiles: 1339

OpenBSD也通过sysctl提供它们,并使用不同的名称。

kern.maxfiles=7030
kern.nfiles=143

Solaris提供了位于kstat:/kmem_cache/kmem_default/file_cache中的buf_inusebuf_max值。
在一些基于Unix的文件系统中,您可能可以捕获lsof -nl的命令行输出以计算当前文件数(尽管这可能会很慢),以及ulimit -n获取最大值。
OSHI从Linux的procfs、macOS、FreeBSD、OpenBSD的sysctl以及Solaris的kstat返回值,以及从上面的命令行中获取AIX的值。
作为OSHI的作者,我可能有偏见,但这可能是跨平台获取这些值的最简单方法。
对于Windows来说,并没有“文件限制”这样的概念。Windows对句柄进行限制。有关这些限制的更多详细信息,请参见此Stack Exchange问题。该问题和答案是OSHI javadocs中所提到的合格语言的来源。

理论上,在64位Windows中,进程可以打开的句柄的最大数量是2的32次方,因为句柄有32位有效位。但实际上,它已被限制为每个进程16,777,216(2的24次方)。在32位Windows中,限制可能是2的16次方

并且

但是,对于使用默认C运行时库的单个进程,则默认限制为512。

还有

不清楚Windows中所有进程的总文件句柄数的最大值。


但是,使用OSHI的方法获取进程的打开文件限制是否正确呢? 例如,当我使用JNA在Ubuntu 22.04上执行getrlimit来获取打开文件限制资源时,硬限制返回1048576,而OSHI则返回9223372036854775807(表示无限制)。 - stackseti
我可以证实,/proc/{pid}/limits 返回 JNA 调用的值作为硬限制 - 1048576 - stackseti
1
@stackseti OSHI当前报告系统范围限制。在Linux中,这是 /proc/sys/fs/file-nr。1048576是每个进程的限制,/proc/sys/fs/nr_open将匹配 getrlimit - Daniel Widdis
目前在OSHI中没有获取每个进程限制的方法吗? - stackseti
1
@stackseti "目前" -- 不过,我刚刚添加了一个问题以添加该功能。 欢迎协作/贡献! - Daniel Widdis

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