此内存使用模式是否表明我的Java应用程序泄漏了内存?

时间:2013-12-05 23:57:07

标签: java

我有一个Java应用程序,等待用户按键然后运行任务。完成后,它会返回并再次等待。我正在使用jvisualvm查看此应用程序的内存配置文件,它显示了一种不断增加的模式。

提交的内存大小为16MB。 应用程序启动时使用的内存为2.7 MB,然后使用中间丢弃(垃圾收集)进行爬升。一旦这个锯齿模式接近16MB,就会出现大幅下降,内存使用量接近4 MB。然而,这个主要的下降点一直在增加。 4MB,6MB,8MB。使用率从未超过16 MB,但整个锯齿模式正朝着16 MB的方向攀升。

我是否有内存泄漏?

由于这是我第一次发布到StackOverflow,因此没有足够的声誉来发布图片。

3 个答案:

答案 0 :(得分:2)

通常会观察到这种锯齿状图案,并不表示内存泄漏。

因为大块垃圾收集比不断收集少量垃圾更有效,JVM会批量收集。这就是你看到这种模式的原因。

答案 1 :(得分:2)

现代SunOracle JVM使用所谓的分代垃圾收集器:

  1. 当收集器运行时,首先尝试部分收集只释放最近分配的内存
  2. 最近创建的仍处于活动状态的对象获得'提升'
  3. 一旦某个对象被提升了几次,即使它已准备好收集,也不会再被部分收集清理
  4. 这些被称为终身的对象只有在需要完整的集合时才会被清理,以便为程序提供足够的空间来继续运行
  5. 所以基本上,你的程序中的一些东西会长时间被快速的'部分'集合所遗漏,这种情况将会持续到JVM决定它必须进行完整的集合。如果你让它走得足够长,你应该最终看到完整的收集发生并且使用量下降到你原来的起点。

    如果这种情况永远不会发生并且你最终得到Out Of Memory异常,那么你可能会有内存泄漏:)

答案 2 :(得分:0)

正如其他人所说,这种行为是正常的。 This是对垃圾收集过程的一个很好的描述。总而言之,JVM使用世代垃圾收集器。绝大多数物体都是非常短暂的,而那些存活时间更长的物体往往会持续更长时间。知道了这一点,GC将首先检查新一代,以避免不必重复检查不太可能无法访问的旧对象。一段时间后,幸存者搬到了老一辈。这种增加的锯齿正是你所看到的 - 上升的低谷是由于老一代人随着幸存者的移动而变得越来越大。如果你的程序运行得足够长,最终检查新一代将无法释放足够的内存,并且它也必须GC也是老一代。

希望有所帮助。