假设您的应用程序执行的很多操作都涉及读取文件的内容。不言而喻,打开然后关闭的文件和生活是好的,除非..新文件进入速度更快,然后旧文件关闭。这是我发现自己处境的一种情况。
现在..有没有办法可靠地知道流程打开了多少文件?与从JVM内部查看ls /proc/my_pid/fd | wc -l
一样可靠的东西吗?
我怀疑答案可能是特定于操作系统的,所以让我补充说我在Linux上运行Java。
答案 0 :(得分:29)
在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());
}
}
}
答案 1 :(得分:9)
如果您想获得java中ls /proc/my_pid/fd | wc -l
的数量,可以使用 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());
}
答案 2 :(得分:7)
为了完成/添加答案:
许多人在基于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
答案 3 :(得分:2)
很抱歉,您可能忽略了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
答案 4 :(得分:0)
在ubuntu中,下面的add_one <- function(data, var, na_if_val = NULL) {
data %>%
mutate(across({{ var }}, as.numeric)) %>%
{if( is.null(na_if_val)
) . # <--- the dot means: "return the preexisting dataframe"
else
na_if(x = ., y = na_if_val)
} %>%
mutate(across({{ var }}, add, 1))
}
命令有效
lsof