在java中是否可以反射性地检查内存泄漏?

在java中是否可以反射性地检查内存泄漏?,java,memory-management,reflection,memory-leaks,profiling,Java,Memory Management,Reflection,Memory Leaks,Profiling,所以,我有了这个想法,写了一些代码,可以在测试中自动检测并指出潜在的内存泄漏,我只是想在实现它之前看看我的想法是否合理 从本质上讲,内存泄漏被定义为越来越多的未使用引用。在爪哇,这种危险比C++更显著地减少了,因为我们没有危险的指针,或者忘记删除()等等。 因此,这限制了在Java中出现内存泄漏的方式。我们可以对一个对象进行静态引用,也可以在当前运行的线程中进行本地引用,就这样,对吗 然后,我的想法是编写一个例程,查看所有已知的项目类文件,并提取所有静态引用。然后一个引用需要被“递归”下来,它拥

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

从本质上讲,内存泄漏被定义为越来越多的未使用引用。在爪哇,这种危险比C++更显著地减少了,因为我们没有危险的指针,或者忘记删除()等等。 因此,这限制了在Java中出现内存泄漏的方式。我们可以对一个对象进行静态引用,也可以在当前运行的线程中进行本地引用,就这样,对吗

然后,我的想法是编写一个例程,查看所有已知的项目类文件,并提取所有静态引用。然后一个引用需要被“递归”下来,它拥有的所有实例引用都需要被计数。一个对象引用需要一定量的内存,而原语需要一定量的内存,我们可以把所有这些加起来。您可以触发此例程一次,以获得基线,然后执行您认为会导致内存泄漏的操作,然后再次运行该例程,并比较结果。可以设置增量阈值,然后您可以手动确定哪些对象故意变大,哪些对象变大,但不应该变大

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

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

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


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

因为Java 1.5有jmap,它可以打印类直方图

因此,这限制了在Java中出现内存泄漏的方式。我们可以对一个对象进行静态引用,也可以在当前运行的线程中进行本地引用,就这样,对吗

不,退房 对于其他原因的非详尽列表,其中大多数是您的方法无法检测到的

在我所从事的项目中,通常情况下,我只能在大量用户的情况下在生产中重现这些错误,因此使用真实的探查器并不总是一种选择。内置此功能可以避免实际运行探查器,并允许大部分时间正常运行,但在生产产品上诊断问题时除外


您始终可以让生产系统写入堆转储(每当发生OutOfMemoryError时,Oracle JVM甚至有写入堆转储的权限)。然后,您可以分析这些堆转储(有各种各样的工具用于此,其中一些工具通过应用一些启发式方法自动查找“泄漏嫌疑犯”)

如果这是可信的,那么现在就有人已经这样做并赚了很多钱。我认为你的想法不会产生我现在无法得到的有用结果。那么你是如何得到这些结果的呢?我之所以想到这一点,是因为我怀疑内存泄漏,但我不知道从哪里开始查找。我认为应该使用Visual VM查找内存泄漏。内存不足时,可以告诉生产JVM转储诊断信息。然后,您可以对该诊断信息进行后期处理,以确定问题。我相信大多数供应商都支持转储hprof信息。