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

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

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

我有内存泄漏吗?

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

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

  1. 当收集器运行它时,首先尝试部分收集只释放最近分配的内存
  2. 最近创建的仍处于活动状态的对象获得“提升”
  3. 一旦对象被提升了几次,即使它已准备好收集,它也不会被部分收集清理干净
  4. 这些被称为tenured的对象只有在需要完整集合时才会被清理,以便为程序提供足够的空间来继续运行

所以基本上,你的程序中的一些东西会长时间被快速的“部分”集合所遗漏,这种情况将会持续到JVM决定它必须进行完整的集合。 如果你让它走得足够长,你应该最终看到完整的集合发生,并且使用率下降到你原来的起点。

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

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

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

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

希望有所帮助。