如何找出Java应用程序当前打开的文件数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16360720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:29:43  来源:igfitidea点击:

How to find out number of files currently open by Java application?

java

提问by James Raitsev

Suppose a lot of what your application does deals with reading contents of files. It goes without saying that files that are opened then closed and life is good unless ... new files come in faster then old files get closed. This is the pickle of a situation I found myself in.

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

Now, is there a way to reliably know how many files are opened by the process? Something that is as reliable as looking at ls /proc/my_pid/fd | wc -lfrom inside the JVM?

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

I suspect the answer may be OS-specific, so let me add that I am running Java on Linux.

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

采纳答案by FDinoff

On Unix, one way is using the ManagementFactoryto get the OperatingSystemMxBeanand if it is a UnixOperatingSystemMXBean, you can use the getOpenFileDescriptorCount()method.

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

Example code:

示例代码:

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());
        }
    }
}

回答by Kent

If you want to get the number of ls /proc/my_pid/fd | wc -lin java, you could use JMX.

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

When you have MBeanServerConnection, you can get attribute "OpenFileDescriptorCount". this will give you the same result as the above ls..|wc -l.

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

also there is another attribute "MaxFileDescriptorCount", which tells your the max count allowed.

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

If you just want to know the value, but not getting it in your code, you could either do your ls..|wc -lway, or read from jconsole(with GUI).

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

NOTE

笔记

ls /proc/my_pid/fd | wc -l

this number indicates how many fd opened by your process(java application). e.g. your business files are counted, also those jars, libraries files are counted too. If you just want to get the count of your business files, you have to implement a counter by yourself. Or, say you want to do it with shellscript, grepsomething out then wc -l

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

EDIT

编辑

add code example, but it is just an example. not written in IDE, not tested with compiler. :)

添加代码示例,但这只是一个示例。不是用 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());
}

回答by Rishitesh Mishra

For the sake of completing/adding to the answer:

为了完成/添加到答案:

Many people uses LSOF in Linux based system to monitor file descriptors and their details. However LSOF lists all kind of FDs(CWD,MEM) which is not returned by UnixOperatingSystemMXBean.getOpenFileDescriptorCount().

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

Details can be found in http://www.ibm.com/developerworks/aix/library/au-lsof.htmlThis may cause some confusion.

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

To clarify UnixOperatingSystemMXBean.getOpenFileDescriptorCount() only shows application opened files descriptors. But LSOF (lsof -a -p ) lists other file descriptors opened by kernel on behalf of the process.

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

To list only application level FDS one can filter out other type of FDs

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

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

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

回答by Артем Баскаков

Sorry for necroposting, but guys, you're ignoring -K option of lsof cause java have threads, each of them have their own FD that are living in /proc/$PID/tasks/fd/

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

and there is A HUGE difference: root@xxx:/root# lsof -p 13553 | wc -l 612 root@xxx:/root# lsof -p 13553 -K | wc -l 112108

并且有一个巨大的区别:root@xxx:/root# lsof -p 13553 | wc -l 612 root@xxx:/root# lsof -p 13553 -K | wc -l 112108