6

我的代码库中有一个问题,我们没有正确关闭文件句柄,或者可能是流。我们最终在非常重的负载下得到了一个 TooManyOpenFiles 异常。根据 lsof 的输出,我们很确定我们知道泄漏在哪里(在我们的日志系统中),但我的问题是:我如何编写一个单元测试来检查,当它完成时,资源是否已正确关闭?有没有办法查询 JRE 以了解当前打开了多少文件?我可以以某种方式拦截文件操作以便监控它们吗?

我怀疑我将不得不检测我的代码以管理所有文件 I/O、计数引用并确保它们以这种方式关闭,但如果有人知道类似于我上面提到的那些想法的自上而下的解决方案,那将是一个巨大的帮助!

4

4 回答 4

3

您可以使用AspectJ之类的面向方面编程 (AOP) 工具添加代码以计算打开/关闭文件FileInputStreamFileOutputStream. 这很容易做到(当然,细节取决于工具)健壮且无创。

于 2011-09-26T18:05:26.407 回答
3

由于您在谈论测试,PowerMock http://code.google.com/p/powermock/可能会成功。如果我没记错的话,它可以模拟静态方法和构造函数。因此,您可以模拟/监视构造函数和关闭方法或释放资源所需的任何内容。

我试图在我的测试中避免它,但在你描述的情况下,它可能值得麻烦。

于 2011-09-26T18:16:36.180 回答
0

看起来你可以通过 JMX 观看。

有人在这里发布代码:http: //java-monitor.com/forum/showthread.php ?t=130

如果您还没有启用 JMX,则必须在 JVM 中启用。

于 2011-09-26T18:12:11.467 回答
0

您可以为普通的 IO 类、FileInputStream 等编写自己的“库”。跟踪(在测试中)调用者打开它的内容、它是否仍然打开、全局列表等。让它包装一个“真实的”FileInputStream。然后在代码中的任何地方使用它,而不是“正常” FileInputStream 等。

然后在你的单元测试结束时你断言WrappedFileInputStreams.assertAllWereClosed或者你有什么。

另一种选择是编写您的方法,以便它们以某种方式接受 FileinputStream 作为参数,然后调用它们,然后断言您的参数在方法结束后“立即关闭”。

或者,如果您知道您将使用 linux,请进行系统调用lsof,它不应将任何文件列为位置“(已删除)”。https://unix.stackexchange.com/a/64737/8337

出于某种原因,在 OS X 上它并不那么容易,它没有显示“(已删除)”,但您仍然可以通过循环lsof -p ...并检查每个文件是否真的存在于文件系统上来检测文件是否已消失......

于 2022-01-06T00:33:18.383 回答