所以,我有了这个想法,可以编写一些代码,可以自动检测并指出测试中潜在的内存泄漏,我只是想在我遇到实现它的麻烦之前看看我的想法是否合理。
本质上,内存泄漏被定义为越来越多的未使用引用。在Java中,与C ++相比,这种危险显着减少,因为我们没有悬挂指针或忘记删除()等的危险。
因此,这限制了我们在Java中发生内存泄漏的方式。我们可以有一个对Object的静态引用,或者我们可以在当前运行的线程中有本地引用,那就是它,对吧?
我的想法是编写一个查看所有已知项目类文件的例程,并提取所有静态引用。然后需要“递归”引用,并且需要对其进行所有实例引用计数。对象引用需要一些内存,而原语占用一些内存,我们可以计算所有内存。您可以触发此例程一次,获取基线,然后执行您认为导致内存泄漏的事情,然后再次运行例程,并比较结果。可以设置增量阈值,然后您可以手动确定哪些对象有目的地变大,哪些对象变大,但不应该有。
这是一个测试工具,当然,在我工作的项目中,通常我只能在生产中重现这些错误,有很多用户,所以使用真实的分析器并不总是一个选项。内置此功能可以节省必须实际运行分析器,并且在大多数情况下允许正常操作,除非在生产产品上诊断问题。
我看到的唯一问题是当前正在运行的线程中的局部变量不能以这种方式访问,但是,知道这种限制,可能需要代码将这些本地(但长期引用)注册到测试类本身,它将在静态变量中保存对这些对象的弱引用,从而允许对引用进行计数。
垃圾收集会是一个问题,所以基本上,我会通过创建一个未引用的对象来“强制”垃圾收集,它会覆盖finalize以在收集时通知我的线程,这会导致我的GC检测器停止阻塞,并且然后运行检漏仪。
所以,我的问题是,这听起来有道理吗?你认为这会产生有用的结果吗?
答案 0 :(得分:2)
因此,这限制了我们在Java中发生内存泄漏的方式。我们可以有一个对Object的静态引用,或者我们可以在当前运行的线程中有本地引用,那就是它,对吧?
没有。查看Creating a memory leak with Java 对于替代原因的非详尽列表,大多数是您的方法无法检测到的。
在我工作的项目中,通常我只能在生产中重现这些错误,有很多用户,所以使用真实的分析器并不总是一种选择。内置此功能可以节省必须实际运行分析器,并且在大多数情况下允许正常操作,除非在生产产品上诊断问题。
您始终可以让生产系统编写堆转储(每当发生OutOfMemoryError时,Oracle JVM甚至会有setting来写堆转储。)。然后,您可以分析这些堆转储(有各种各样的工具,其中一些通过应用一些启发式方法自动找到“泄漏嫌疑人”)。
答案 1 :(得分:1)
从Java 1.5开始,你有jmap可以打印类直方图。