Как узнать количество файлов, открытых в настоящее время Java-приложением?
Предположим, многое из того, что делает ваше приложение, связано с чтением содержимого файлов. Само собой разумеется, что файлы, которые открываются, затем закрываются, и жизнь хороша, если... новые файлы приходят быстрее, чем старые файлы закрываются. Это рассеяние ситуации, в которой я оказался.
Теперь, есть ли способ достоверно узнать, сколько файлов открывается процессом? Нечто такое же надежное, как просмотр ls/proc/my_pid/fd | wc -l
ls/proc/my_pid/fd | wc -l
изнутри JVM?
Я подозреваю, что ответ может зависеть от ОС, поэтому позвольте мне добавить, что я использую Java на Linux.
Ответы
Ответ 1
В 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());
}
}
}
Ответ 2
Если вы хотите получить номер ls /proc/my_pid/fd | wc -l
в java, вы можете использовать JMX.
Когда у вас есть MBeanServerConnection
, вы можете получить атрибут "OpenFileDescriptorCount
". это даст вам тот же результат, что и выше ls..|wc -l
.
также существует еще один атрибут "MaxFileDescriptorCount
", в котором указано, что максимальное количество допустимо.
Если вы просто хотите знать значение, но не получаете его в своем коде, вы можете либо сделать свой способ ls..|wc -l
, либо прочитать из jconsole
(с графическим интерфейсом).
Примечание
ls /proc/my_pid/fd | wc -l
это число указывает, сколько fd было открыто вашим процессом (приложение java). например учитываются ваши бизнес файлы, также учитываются эти банки, файлы библиотек. Если вы просто хотите получить кол-во своих бизнес файлов, вам придется самостоятельно выполнить счетчик. Или, скажем, вы хотите сделать это с помощью 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());
}
Ответ 3
Ради заполнения/добавления к ответу:
Многие люди используют LSOF в Linux-системах для мониторинга файловых дескрипторов и их деталей. Однако LSOF перечисляет все виды FD (CWD, MEM), которые не возвращаются UnixOperatingSystemMXBean.getOpenFileDescriptorCount().
Подробности можно найти в 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