如果垃圾收集器运行异常,是内存泄漏吗?

时间:2012-09-16 11:09:24

标签: java garbage-collection

我开发了一个J2ME Web浏览器应用程序,它工作正常。我正在测试它的内存消耗。在我看来,它有一个内存泄漏,因为代表内存监视器(无线工具包)的消耗内存的绿色曲线在浏览器完成的每7个请求中达到最大分配内存(即687768字节)(即,当最终用户在Web浏览器中从一个页面导航到另一个页面7个页面之后,垃圾收集器运行并释放分配的内存。

我的问题是:

  • 当垃圾收集器每7页导航自动运行时,它是否是内存泄漏?
  • 我是否需要每次请求手动运行一次垃圾收集器(System.gc())以防止达到最大分配内存?

请指导我,谢谢

5 个答案:

答案 0 :(得分:3)

要确定它是否是内存泄漏,您需要更多地观察它。

根据您的描述,即一旦达到最大内存,GC就会启动并且能够释放内存以供您的应用程序运行,这听起来不像是有泄漏。

此外,你不应该自己打电话给GC

  1. 这只是一个指示
  2. 可能会影响影响其性能的基础算法。
  3. 您应该专注于您的应用程序在如此短的时间内需要如此多的内存。

答案 1 :(得分:1)

  

我的问题是:当垃圾收集器每7页导航自动运行时,它是否是内存泄漏?

不一定。它也可能是:

  • 您的堆太小,无法解决您要解决的问题,或

  • 您的应用程序正在高速生成(可收集的)垃圾。

事实上,鉴于您提供的数字,我倾向于认为这主要是堆大小问题。如果GC运行之间的间隔随着时间的推移而减少,那么这将是指向内存泄漏的证据,但如果速率平均保持稳定,则表明内存使用率和回收率处于平衡状态;即没有泄漏。

  

我是否需要每次请求手动运行一次垃圾收集器(System.gc())以防止达到最大分配内存?

没有。没有。

调用System.gc()无法解决内存泄漏问题。如果它是真正的内存泄漏,那么调用System.gc()将不会回收泄漏的内存。事实上,你要做的就是让你的应用程序运行得很快......假设JVM没有完全忽略这个调用。


直接和间接证据表明HotSpot JVM的默认行为是为了遵守System.gc()调用:

从Java 7源代码:

./的openjdk /热点/ SRC /共享/ VM /运行/ globals.hpp

  product(bool, DisableExplicitGC, false,                                   \
          "Tells whether calling System.gc() does a full GC")               \

其中false是选项的默认值。 (请注意,这是代码树的OS / M / C独立部分。)

答案 2 :(得分:1)

我写了一个图书馆,努力强制GC。如前所述,System.gc()是异步的,不会自行执行任何操作。您可能希望使用此库来分析您的应用程序并找到生成过多垃圾的位置。您可以在this article中详细了解GC问题。

答案 3 :(得分:0)

这是(半)正常行为。在堆大小达到某个阈值之前,不会收集可用(未引用)存储,从而触发收集周期。

您可以通过更多“堆感知”来降低GC周期的频率。例如,许多程序中的一个常见错误是使用子字符串解析字符串,不仅解析最左边的单词,而且还通过向右子字符串缩短剩余的字符串。不容易避免为单词创建新的String,但可以轻松避免重复地对原始字符串的“尾部”进行子串。

运行System.GC将无所作为 - 在大多数平台上它都是无操作的,因为它经常被滥用。

请注意(在脑死亡的Android之外)你不能在Java中拥有真正的“内存泄漏”(除非存在严重的JVM错误)。 Java中通常所说的“泄漏”是指未能删除对永远不会再次使用的对象的所有引用。例如,您可能会继续将数据放入链中,并且永远不会清除指向不再使用链的远端的内容的指针。产生的症状是使用的MINIMUM堆(即GC运行后的大小)每个循环都会持续上升。

答案 4 :(得分:0)

增加其他优秀答案:

看起来你将内存泄漏垃圾回收混淆。

内存泄漏是指未使用的内存无法进行垃圾回收,因为它仍然在某处提供引用(尽管它们不用于任何内容)。

垃圾收集是指一个软件(垃圾收集器)自动释放未引用的内存。

您不应手动调用垃圾收集器,因为这会影响其性能。