Есть ли утечка дескриптора файла при использовании сокетов на платформе Linux?

Если я открываю и закрываю сокет, вызывая, например,

Socket s = new Socket( ... );
s.setReuseAddress(true);
in = s.getInputStream();
...
in.close(); 
s.close();      

Linux утверждает, что этот сокет по-прежнему открыт или, по крайней мере, файловый дескриптор для соединения является presen. При запросе открытых файлов для этого процесса lsof, есть запись для закрытого соединения:

COMMAND  PID   USER   FD   TYPE DEVICE     SIZE   NODE NAME
java    9268 user    5u  sock    0,4           93417 can't identify protocol

эта запись остается до тех пор, пока программа не будет закрыта. Есть ли другой способ окончательно закрыть розетку? Я немного беспокоюсь, что мое приложение java может блокировать многие файлы дескрипторы. Возможно ли это? Или java сохраняет эти сокеты для повторного использования, даже если установлен ReuseAdress?

5 ответов


Если все эти сокеты находятся в состоянии TIME_WAIT, это нормально, по крайней мере, на некоторое время. Проверьте это с помощью netstat; обычно сокеты висят в течение нескольких минут, чтобы убедиться, что беспорядочные данные из сокета успешно выбрасываются перед повторным использованием порта для нового сокета.


вы также можете проверить /proc/<pid>/fd каталог будет содержать все ваши открытые дескрипторы файлов. Если файл исчезнет после закрытия сокета, вы не столкнетесь с какими-либо проблемами (по крайней мере, с вашими файловыми дескрипторами :).


Я думаю, это не проблема вашей программы.

в SUN_Java, когда будет загружен собственный lib, связанный с сокетом, будет создан MAGIC_SOCK fd.

запись на MAGIC_SOCK приведет к исключению Connect Rest, а чтение на MAGIC_SOCK приведет к EOF.

узел magic_sock был полностью закрыт, а сам magic_sock наполовину закрыт, и состояние останется "не может идентифицировать протокол".


может быть, это сокет какого-то другого протокола ("не могу идентифицировать протокол", а?) используется внутренне в реализации для чего-то, что создается на первом сокете.

вы пытались неоднократно создавать сокеты и закрывать их, чтобы увидеть, действительно ли эти сокеты сохраняются? Кажется вероятным, что это единичный случай.

Java, вероятно, использует сокеты внутри для многих вещей - это может быть Unix, Netlink (под Linux) или какой-то другой тип сокета.


создайте небольшой скрипт bash для мониторинга открытых сокетов для определенного приложения или pid и запустите его во время тестирования java-приложения.

Я все равно сомневаюсь, что в этой вещи есть какие-либо утечки, поскольку сокеты очень используются в мире linux/unix, и такая проблема будет очень быстро всплывать