假设您的应用程序所做的很多事情都是处理读取文件的内容。不用说,打开然后关闭的文件和生活是美好的,除非......新文件进来的速度比旧文件关闭得快。这是我发现自己所处的困境。
现在,有没有办法可靠地知道该进程打开了多少文件?像ls /proc/my_pid/fd | wc -l
从 JVM 内部观察一样可靠的东西?
我怀疑答案可能是特定于操作系统的,所以让我补充一下,我在 Linux 上运行 Java。
假设您的应用程序所做的很多事情都是处理读取文件的内容。不用说,打开然后关闭的文件和生活是美好的,除非......新文件进来的速度比旧文件关闭得快。这是我发现自己所处的困境。
现在,有没有办法可靠地知道该进程打开了多少文件?像ls /proc/my_pid/fd | wc -l
从 JVM 内部观察一样可靠的东西?
我怀疑答案可能是特定于操作系统的,所以让我补充一下,我在 Linux 上运行 Java。
在 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());
}
}
}
如果您想获取ls /proc/my_pid/fd | wc -l
java 中的数量,可以使用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());
}
为了完成/添加到答案:
许多人在基于 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
很抱歉发布了 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
在 ubuntu 中,以下lsof
命令有效
sudo lsof -c java