我有一个Java程序,平均运行2周后会卡住并产生以下错误:
Caused by: java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:415)
at sun.nio.ch.Net.socket(Net.java:408)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:105)
这告诉我许多插座已打开但从未关闭。 在深入研究程序设备之前,我开始检查我可以从linux本身获取哪些信息。我正在使用Redhat。
然后,提出了几个问题如下:
见
[ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
592
[ec2-user@ip-172-22-28-102 ~]$ sudo lsof -a -p 32085 | wc -l
655
似乎没有,因为如果我执行以下操作,我会得到相同的信息:
[ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/task/22386/fd | wc -l
592
[ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
592
如果我直接从/ proc /下面转到该线程。
THX
答案 0 :(得分:5)
有没有办法从proc stat info中知道哪个线程创建了哪个文件描述符?
我很确定这里的答案是“不”。文件描述符由进程打开,而不是线程(并且对于由同一进程生成的所有线程都可见)。
为什么以下命令不能提供相同的输出?
首先,-a
的{{1}}参数在这种情况下似乎是无操作。具体而言,该男子称其“使列表选择选项成为AND,如上所述”。所以你真的只是在跑步:
lsof
这将打印除打开文件描述符(例如内存映射文件,当前工作目录等)以外的内容,而sudo lsof -p 32085
仅包含打开的文件描述符。所以你得到不同的结果,因为你要求不同的信息。
答案 1 :(得分:0)
您收到该消息的唯一原因是您已打开文件,并且在使用后您没有关闭它们。您的Java应用程序中有文件描述符泄漏。 Java程序员通常不会检查内存,因为垃圾收集器会处理未引用的对象。如果保存文件描述符而不关闭某些数据结构,或者在使用后没有关闭文件,则可以达到允许进程的最大限制(这是按进程控制的,可以由{{1}更改} shell命令)
但是如果您的问题是文件描述符泄漏,那么推高ulimit只会延迟问题一段时间。必须关闭文件描述符,否则您将遇到麻烦。
答案 2 :(得分:-1)
我今天刚刚遇到这个差异,解释是lsof考虑了更多类型的文件,比如内存映射对象,运行时库等