49

假设您的应用程序所做的很多事情都是处理读取文件的内容。不用说,打开然后关闭的文件和生活是美好的,除非......新文件进来的速度比旧文件关闭得快。这是我发现自己所处的困境。

现在,有没有办法可靠地知道该进程打开了多少文件?像ls /proc/my_pid/fd | wc -l从 JVM 内部观察一样可靠的东西?

我怀疑答案可能是特定于操作系统的,所以让我补充一下,我在 Linux 上运行 Java。

4

5 回答 5

47

在 Unix 上,一种方法是使用ManagementFactory来获取OperatingSystemMxBean,如果是UnixOperatingSystemMXBean,则可以使用该getOpenFileDescriptorCount()方法。

示例代码:

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import com.sun.management.UnixOperatingSystemMXBean;

public class OpenFileCount{
    public static void main(String[] args){
        OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
        if(os instanceof UnixOperatingSystemMXBean){
            System.out.println("Number of open fd: " + ((UnixOperatingSystemMXBean) os).getOpenFileDescriptorCount());
        }
    }
}
于 2013-05-03T14:38:06.073 回答
11

如果您想获取ls /proc/my_pid/fd | wc -ljava 中的数量,可以使用JMX

当你拥有时MBeanServerConnection,你可以获得属性“ OpenFileDescriptorCount”。这将为您提供与上述相同的结果ls..|wc -l

还有另一个属性“ MaxFileDescriptorCount”,它告诉您允许的最大计数。

如果您只想知道该值,而不是在代码中获取它,您可以按照自己的ls..|wc -l方式进行,或者从jconsole(使用 GUI)读取。

笔记

ls /proc/my_pid/fd | wc -l

此数字表示您的进程(java 应用程序)打开了多少 fd。例如,您的业务文件被计算在内,那些罐子、库文件也被计算在内。如果您只想获取业务文件的计数,则必须自己实现一个计数器。或者,说你想用 shellscript 来做,grep然后wc -l

编辑

添加代码示例,但这只是一个示例。不是用IDE编写的,没有用编译器测试过。:)

ObjectName oName = new ObjectName("java.lang:type=OperatingSystem");
MBeanServerConnection conn ; // you should get the connection following the api, take a look the java api/ google some example
javax.management.AttributeList list = conn.getAttributes(oName, new String[]{"OpenFileDescriptorCount", "MaxFileDescriptorCount"});
for(Attribute attr: list.asList()){
    System.out.println(attr.getName() + ": " + attr.getValue());
}
于 2013-05-03T14:31:47.393 回答
9

为了完成/添加到答案:

许多人在基于 Linux 的系统中使用 LSOF 来监视文件描述符及其详细信息。但是 LSOF 列出了 UnixOperatingSystemMXBean.getOpenFileDescriptorCount() 未返回的所有类型的 FD(CWD,MEM)。

详细信息可以在http://www.ibm.com/developerworks/aix/library/au-lsof.html中找到。 这可能会引起一些混乱。

澄清 UnixOperatingSystemMXBean.getOpenFileDescriptorCount() 仅显示应用程序打开的文件描述符。但是 LSOF (lsof -a -p) 列出了内核代表进程打开的其他文件描述符。

要仅列出应用程序级别的 FDS,可以过滤掉其他类型的 FD

lsof -a -p yourprocid -d ^txt,^mem,^cwd,^rtd,^DEL

于 2014-10-14T07:26:15.557 回答
3

很抱歉发布了 necroposting,但是伙计们,您忽略了 lsof 的 -K 选项,因为 java 有线程,每个线程都有自己的 FD,它们位于 /proc/$PID/tasks/fd/

并且有很大的不同:

root@xxx:/root# lsof -p 13553 | wc -l
612
root@xxx:/root# lsof -p 13553 -K | wc -l
112108
于 2020-03-05T09:37:40.990 回答
1

在 ubuntu 中,以下lsof命令有效

sudo lsof -c java
于 2020-10-01T13:21:22.783 回答