Java Can JVisualVM“;堆转储";按钮释放存储器?

Java Can JVisualVM“;堆转储";按钮释放存储器?,java,memory,jvisualvm,heap-dump,Java,Memory,Jvisualvm,Heap Dump,我有一个很奇怪的问题。 我正在开发一个基于EclipseEquinox的OSGi应用程序;它是使用OSGi日志服务(Equinox实现)开发的,现在我正在使用ApacheFelixOSGi日志服务实现对其进行测试 在API/代码方面,一切正常:OSGi日志服务是标准的,所以我可以毫无问题地从Equinox切换到Felix 然而,我观察到了这种奇怪的行为:我将应用程序作为控制台程序启动,以查看控制台上的日志输出,并将其附加到JVisualVM以分析内存使用情况;JVisualVM图显示了80 MB

我有一个很奇怪的问题。 我正在开发一个基于EclipseEquinox的OSGi应用程序;它是使用OSGi日志服务(Equinox实现)开发的,现在我正在使用ApacheFelixOSGi日志服务实现对其进行测试

在API/代码方面,一切正常:OSGi日志服务是标准的,所以我可以毫无问题地从Equinox切换到Felix

然而,我观察到了这种奇怪的行为:我将应用程序作为控制台程序启动,以查看控制台上的日志输出,并将其附加到JVisualVM以分析内存使用情况;JVisualVM图显示了80 MBs的已用堆

13小时后,平均堆大小达到220 MBs,因此我决定分析堆转储,并按下“堆转储”按钮:此操作后,JVisualVM图形显示使用的堆大小为20(min)-35(max)MBs(?!),该值为常量

“堆转储”操作是否可以释放近200 mbs?若有,原因为何

我从未在Equinox OSGi日志服务实现中看到过这种行为,因此我怀疑Felix日志与此问题有关


谢谢

为什么你会被GC困扰?如果内存被正确释放,就没有必要担心。但如果您想发现堆增长的原因(即使您认为它不是泄漏),请查看以下内容:

“堆转储”操作是否可以释放近200 mbs?若有,原因为何


是的,它可以。我没有研究过代码,但我非常确定它调用时第二个参数设置为true(如果从jconsole或JVisualVM的MBeans扩展调用它,这是默认值)。根据我的经验,这样做会在转储堆之前触发显式gc,这可能就是“为什么?”。

为什么?因为当您想查找内存泄漏时,您不想获取那些没有引用但尚未被垃圾收集的对象。因此VisualVM在获取堆转储之前会触发完全GC。@Tomas Hurka是吗?当然,这就是为什么你有这个选择(尽管其他选择也有很好的用途)。我把OP的“为什么?”解释得更像“为什么它会释放内存?”而答案是“因为VisualVM要求它这么做”,在堆转储之前。我明白了。“你能告诉我另一种选择的真正好的用途是什么吗?”托马斯·赫卡(Thomas Hurka)我使用它的大多数时候是在我想找出无意中的浪费的时候。通常是在使用MAT之类的工具来确定GC性能差的原因时。如果您怀疑您的程序正在某个地方的内部循环中分配许多临时对象,您可能希望在收集之前查看堆,以了解它们是什么。大多数情况下,您希望让GC完成其工作,但有时它有助于提高性能,以避免在CPU密集型代码中分配/GC。在现实世界中,特别是在金融和其他低延迟领域,您确实希望最小化GC必须完成的工作,分析堆并找出可能的浪费。“让GC完成它的工作”对于大多数java应用程序来说是一个很好的策略,但当一个25毫秒的句号可以花费一个好的开发人员每年所花费的成本时,就不是了。