内存泄漏总是需要一个长期存在的对象?

时间:2009-09-11 21:06:42

标签: java memory-leaks

这句话是真实的,错误的还是制定不当的:

“在Java中,内存泄漏必须始终以某种方式与长期对象相关。”

在这种情况下,我只是指常规对象,而不是一般的系统资源(文件描述符等)。

长寿命对象的一个​​示例可能是单例(通常以任何速率实现),只要应用程序正在运行,它就会存在。

7 个答案:

答案 0 :(得分:10)

误导。

虽然声明在技术上是正确的,但内存泄漏是由比预期寿命更长的对象引起的。

答案 1 :(得分:2)

声明是正确的,但制定不当恕我直言。在不再需要仍然被引用的对象后,会出现内存泄漏。

我能想到的唯一其他内存泄漏原因是Java应用程序无法释放JNI本机库中的资源。

有趣的文章here

答案 2 :(得分:2)

  

“在Java中,内存泄漏必须始终以某种方式与长期存在的对象相关联。”

     

长期存在的对象是Singleton,或者只要应用程序正在运行就会存在。

我们可以稍微改变一下这个陈述,并以问题的形式对其进行短语。你可以问:

  

是否有可能在Java应用程序中出现与Singleton或其他核心组件无关的内存泄漏(设计时间很长)?

正如我们所知,许多人已经指出,Java上下文中的内存泄漏本质上是对象,其中存在无意的强引用,使它们对垃圾收集器不可用。

为了回答我们的新问题,我们需要设想一个场景,其中我们有一对对象,它们在移出作用域后通常会被垃圾收集,但创建了一个循环引用(两个或多个对象)彼此有很强的参考价值)。这里会强烈引用这些对象,因为它们都超出了范围,所以它们不再与任何“长寿”对象相关联。它们会被认为是泄漏吗?

要回答这个问题,kdgregory在他的博客中发布了一篇名为“Java Reference Objects or 'How I Learned to Stop Worrying and Love OutOfMemoryError'”的文章:

  

您可能想知道如果您有一个循环引用会发生什么:对象A包含对对象B的引用,其中包含一个返回A的引用。答案是标记扫描收集器不会被欺骗:如果没有A一系列强有力的参考文献也无法达到B,那么它们就有资格收藏。

答案 3 :(得分:1)

内存泄漏也可能由短期Java对象引起,这些Java对象在Java内存模型之外分配内存而不释放它。这个内存不会被Java进程泄露,但它仍然可能导致你的系统资源不足。

因此,请务必检查Java程序正在调用的其他进程/程序。

答案 4 :(得分:0)

取决于长期存在的具体情况,以及JRE错误的包含/排除,以及内存泄漏的含义(仅仅一半的应用程序实时内存漏洞是什么?),以及一些垃圾收集器特殊情况(G1应改善这种情况)等等......

嗯,没有进一步背景的问题制定得很差,但是,与Pyrolistical相反,我倾向于说它在技术上是错误的,因为对于内存泄漏的任何实际定义,我认为与你所描述的这种长寿命对象无关它们。

当然,人们可以说没有对堆栈的引用,最终取决于main的执行时间,或某些其他根引用,什么都不存在;但是有了这样的语义,这个问题变得毫无意义。这就像没有电脑说我无法运行Java应用程序。万岁,赢得了0美元的价格。

答案 5 :(得分:0)

因为Java真正分配内存的唯一时间是它创建对象(好吧,对象和数组,但是相同的差异),这绝对是真的,但不是很有用。

说对象为什么长寿是更有用的。

如果您正在撰写论文或其他内容,我会描述对象树的“根”,它会导致保留对象。

这些包括:

  • 堆栈(任何线程)上的临时变量
  • 静态变量(来自任何类)
  • JNI原生代码的特殊引用

我相信还有更多,我抄下来的文件感觉很旧。我知道RMI可以保存未被回收的引用(我猜可能属于“JNI”子弹)

答案 6 :(得分:0)

首先要确定一些事项:

  • 从其他对象引用对象,并且可以将正在运行的程序的整体可视化为引用其他对象的对象图。
  • 根据定义,如果对象无法被活动线程访问,则可以对其进行垃圾回收。
  • 可以有意或无意地创建一个应用程序,它会重复创建对象,然后永远不会让这些对象被垃圾回收。在长时间运行的程序中反复做这件事,你会发现明显的内存泄漏。

“长时间运行”,“明显”和“重复”可能有不同的值,但想法是内存泄漏是最后一点。因此,如果你说内存泄漏与一个长期存在的对象相关联,那么我说这会产生误导 - 对象占用内存,所以当然它们与某种对象相关联,但原因在于应用程序设计,不是对象引用层次结构或垃圾收集器行为。

实际上,要说内存泄漏总是与“常规”长寿命对象相关联 - 我会说错误。但仍然误导,如上所述。