查找“错误”原因的任何Java调试提示;“打开的文件太多”;

查找“错误”原因的任何Java调试提示;“打开的文件太多”;,java,debugging,stream,filenotfoundexception,Java,Debugging,Stream,Filenotfoundexception,我是在linux环境下开发的,该系统旨在长时间连续运行。经过一夜的测试,我们看到FileNotFoundException,并显示一条消息“打开的文件太多”。我们开始在系统中的不同时间记录lsof命令的输出,以查看是否可以看到发生了什么。我们注意到许多未命名的管道打开了。所以我想这是因为文件流没有关闭。我在源代码中搜索所有使用的*流对象,并确保它们都在finally{}块中关闭。是否有其他Java对象类型我可以搜索,但我可能不会关闭它们,从而导致所有这些未命名管道被打开 此外,我的ulimit是

我是在linux环境下开发的,该系统旨在长时间连续运行。经过一夜的测试,我们看到FileNotFoundException,并显示一条消息“打开的文件太多”。我们开始在系统中的不同时间记录lsof命令的输出,以查看是否可以看到发生了什么。我们注意到许多未命名的管道打开了。所以我想这是因为文件流没有关闭。我在源代码中搜索所有使用的*流对象,并确保它们都在finally{}块中关闭。是否有其他Java对象类型我可以搜索,但我可能不会关闭它们,从而导致所有这些未命名管道被打开


此外,我的ulimit是1024,我还搜索了*Writer,并确保它们也都已关闭。

可能值得一看。它旨在帮助解决这类问题,尽管我自己从来没有机会尝试过这种功能。

我假设您的ulimit是ulimit-n的输出。1024是生产系统中允许使用的相当少的文件描述符。对于调试步骤,与其在随机时间运行lsof并尝试关联,为什么不捕获FileNotFound异常并运行Runtime.exec(“lsof”)呢并将输出打印到日志文件中,以便相当准确地了解问题发生时使用了哪些文件描述符。

其他可能泄漏文件描述符的类有
FileChannel
RandomAccessFile
-后者甚至似乎没有终结器,所以它的泄漏可能是永久性的。

未命名管道?能否粘贴lsof输出的采样线?您是否正在使用可能是问题一部分的任何第三方库?此外,您是否正在创建任何tmp文件。。。。为什么不试着增加ulimit呢。同时寻找套接字。。。我认为Runtime.exec可能会使用管道来获取stdin/stdout。在这种情况下,当文件描述符用完时,它将不再工作。这是一个很好的观点。我几乎可以肯定您使用标准输入和标准输出管道是正确的,但是如果这是一个间歇性问题,您经常接近极限,偶尔碰到它,触发FileNotFound异常,那么如果您在检查lsof之前短暂睡眠,它可能在实践中仍然有效。@extraneon是正确的。一旦遇到FileNotFound异常,Runtime.exec将无法用于lsof命令。这就是为什么我们在编写代码时会定期这样做。在对YourKit和其他分析器进行研究之后,我意识到我使用的IDE实际上内置了一个分析器。在使用任何剖析器之前,我们最终发现了这个问题,但看起来这些剖析工具肯定是未来的发展方向。我一有时间就得和一个玩。谢谢你的提示。那么问题的根本原因是什么呢?5年后的今天,我不记得问题最终是什么了。我模糊地记得那是件愚蠢的事。我们做了大量的线程工作,项目的复杂性真的失控了,这无疑使我们更难识别问题。