-1

所以,我有了这个想法,写一些代码可以自动检测并指出测试中潜在的内存泄漏,我只是想看看我的想法是否合理,然后再去实现它。

本质上,内存泄漏被定义为越来越多的未使用引用。在 Java 中,与 C++ 相比,这种危险显着降低,因为我们没有悬空指针或忘记 delete() 等危险。

所以这限制了我们在 Java 中发生内存泄漏的方式。我们可以有一个对象的静态引用,或者我们可以在当前运行的线程中有本地引用,就是这样,对吧?

我的想法是编写一个例程,查看所有已知的项目类文件,并提取所有静态引用。然后需要向下“递归”引用,并且需要向上计数它所具有的所有实例引用。对象引用占用一定数量的内存,而基元占用一定数量的内存,我们可以统计所有这些。您可以触发该例程一次,以获得基线,然后执行您认为会导致内存泄漏的事情,然后再次运行该例程并比较结果。可以设置一个增量阈值,然后您可以手动确定哪些对象有目的地变大,哪些对象变大了,但不应该有。

当然,这是一个测试工具,但是,在我从事的项目中,通常我只能在生产中重现这些错误,有很多用户,所以使用真正的分析器并不总是一种选择。内置此功能可以避免实际运行分析器,并且在大多数情况下都可以正常运行,除非在生产产品上诊断问题时。

我看到的唯一问题是,当前正在运行的线程中的局部变量无法以这种方式访问​​,但是,知道这一限制,可能需要代码将这些本地(但长期引用)注册到测试类本身,这将在静态变量中保存对这些对象的弱引用,从而允许对引用进行计数。

垃圾收集将是一个问题,所以基本上,我会通过创建一个未引用的对象来“强制”垃圾收集,它会覆盖 finalize 以在收集它时通知我的线程,这将导致我的 GC 检测器停止阻塞,然后运行检漏仪。

所以,我的问题是,这听起来合理吗?你认为这会产生有用的结果吗?

4

2 回答 2

2

所以这限制了我们在 Java 中发生内存泄漏的方式。我们可以有一个对象的静态引用,或者我们可以在当前运行的线程中有本地引用,就是这样,对吧?

否。请查看使用 Java 创建内存泄漏,以 获取替代原因的非详尽列表,您的方法无法检测到其中大部分。

在我从事的项目中,很多时候我只能在生产中重现这些错误,有很多用户,所以使用真正的分析器并不总是一种选择。内置此功能可以避免实际运行分析器,并且在大多数情况下都可以正常运行,除非在生产产品上诊断问题时。

您始终可以让生产系统写入堆转储(Oracle JVM 甚至可以设置在发生 OutOfMemoryError 时写入堆转储。)。然后,您可以分析这些堆转储(有多种工具,其中一些通过应用一些启发式方法自动找到“泄漏嫌疑人”)。

于 2012-09-17T17:42:25.303 回答
1

从 Java 1.5 开始,您就有了可以打印类直方图的 jmap。

于 2012-09-17T17:39:28.470 回答