以自动方式查找泄漏内存的JUnit测试

我们问题的根源是单身人士。 但单身人士很难打破,与此同时我们有很多unit testing使用单身人士而不用小心在tearDown()方法中完全清除它们。 我认为检测这些测试的好方法是寻找内存泄漏。 如果在tearDown()和System.gc()之后使用的内存大于测试开始时使用的内存,则测试泄漏或类加载器加载更多类。 有没有办法自动检测这类问题?

我完全赞同其他海报,监视内存使用情况并不是一种可行的方法来跟踪它 – System.gc()不会按照您的预期行事,或者具有足够的精确度来实现您的目标。

您将需要一个工具,可以让您检查参考图并显示分配调用堆栈。

我使用了来自Borland的OptimizeIt和来自ej-technologies的JProfiler ,两者都取得了成功(快速谷歌显示OptimizeIt现在已经死了。)

还有可能使用JVMTI为这个特定问题组合一个更好的监视器。

编辑 :很奇怪,但是当我回顾这个答案时,我接到了Embarcadero的电话,他显然已经购买了OptimizeIt,做了一些更新,现在以J Optimizer的名义进行营销。

只是一个想法:如果你有两个空的测试一个接一个地运行,第二个不应该在teardown()之后使用不同的内存。 如果是这样,您(可能)在setup()/ teardown()系统中的某处有泄漏。

我不认为这是一个好方法。 System.gc()不能保证完全清理任何未使用的对象。

如果你的根本问题是你有unit testing最终使用全局数据(单例)而没有正确清理它们,你应该攻击根问题:这些unit testing。 找到所有不使用tearDown()测试,或查找使用特定单例的所有测试,应该不会太难。

如果您的Singleton仅用于初始化一次,您可以使用代码检查重新初始化并在检测到时记录当前堆栈。 然后,如果您检查堆栈,您将看到哪个测试得到了滚动,您可以检查JUnit日志以查看之前的测试运行情况。

在更彻底地解决这个问题方面,我建议你不要检测它,而是建议你有一个单例初始化程序来记住它初始化的内容,并且有一个拆卸方法可以拆除它初始化的所有内容。 这样一来,测试可以只通过这个类进行初始化,而且只需要在拆解时做一件事。

我也认为Carl Manaster的建议很好,但是如果你使用的是JUnit4,那么你可以在超类中运行一个拆卸方法,而不必记得调用super。 除非您使用JUnit3 GUI,否则JUnit4应该是替代品。 唯一的办法是利用它的新function来迁移整个测试,你不能同时拥有同一个类。 因此,与这些单例交互的测试必须一次迁移一个完整的测试类。

您可以使用Eclipse Memory Analyzer自动分析每次测试后获取的堆转储,或者在所有测试之后可能更好。 MAT可以相当自动地发现内存泄漏。