2010-01-08 141 views
6

我有一个正在运行的java webapp,我用visualVM监视可能的内存泄漏?

这里的堆的图表:

heap http://www.freeimagehosting.net/uploads/9bb3841450.png

的用两套请求,一个在3:20,另一个在4:40 aprox的测试(它们在图中所表示唯一的两个峰值)。

我的问题是:这是否意味着我有内存泄漏?我担心中间部分,虽然GC运行,但堆始终保持在250MB。

非常感谢您的见解。

+1

样本大小为2并不能提供足够的信息来声明泄漏。是的,可以隐藏在该图中:右侧的分配大小大于左侧的分配大小。或者,可以像* binil *提到的那样,只是有些物体被提升到了终身代,而你没有一个主要的GC。 – kdgregory

+0

真的,确定是否有泄漏的唯一方法是比较一段时间内保留的活动对象的数量。我发布了一篇关于如何分析堆转储的文章(这里)(http://www.kdgregory.com/index.php?page=java.outOfMemory)。 – kdgregory

回答

5

在3:20的第一个请求导致了一些内存被保留,但注意到第二个请求后的GC回收了大部分内存。我也认为主要的气相色谱是在4:40的第二次请求后才执行的。

看起来没有泄漏。我的理论是,在3:20的请求导致年轻一代填满,而由此产生的小型GC向一些老一代推销了一些东西。下一个主要的GC由于4:40的请求而导致大部分问题得到了解决。

您可以通过使用一个分析器在3:20发出的一个同样的请求之前,以纪念堆,迫使一个完整的GC,然后检查哪些对象挥之不去验证这一点。我不确定VisualVM是否允许您(1)标记堆并(2)强制执行完整的GC,但OptimizeIt曾经这样做。

+0

非常感谢。你能指出一个很好的参考文件来追踪所有这些概念吗? (年轻一代,老一代,不同类型的GC运行等) –

+1

http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html可能会帮助 –

+0

事实上,使用'visualGC'插件显示对象被提升到堆的另一部分。 –

0

你是说在3:20之前没有请求吗?如果是这样,比我会说我没有看到任何泄漏的证据。

我不知道你的应用程序,但是对于一些在第一次使用该应用程序时初始化JVM的生命周期的对象而言,它是典型的(基于体系结构/设计)。

0

您使用的是什么JRE?堆/ GC相关参数传递给应用程序?

峰值并不差(如果服务器有更多的待办事项,则意味着峰值增加)。但是看起来不太好,以至于4:40之后的水平(当负载再次降低时)随着负载之前的水平上升而升高。不过,这并不需要是...

现在你应该看看更详细,哪些对象或对象的图形都保存在堆中。所以,做同样的测试再次运行,包括(与分析器):

  • 负载离开前达
  • 负载下山后(一定要做好手动GC触发)采取堆快照采取堆快照

现在你应该分析差异和你是否看到奇怪的对象,应该已经被垃圾清理。

0

JvisualVM允许你强制垃圾收集。

尝试使用,看看会发生什么。

+0

它实际上强制它,还是它调用System.gc()? –

+0

我相信它会强制它。也许它只是Sun JVM。 –

+0

它实际上调用'System.gc()'它不强制任何东西。 –

-1

这是什么意思,内存泄漏?我认为像SUN这样的JVM实现并不会有这样一个疯狂的bug。当你没有参考内存位置(僵尸)或者你没有任何回收它的可能性时,理想地使用内存泄漏字。如果您在编程过程中遇到了错误的编程习惯,那么您不得不引用不再使用的对象,并且它们在更大的范围内(使用寿命),则会消耗更多的内存,而不会让GC选择重新采集它。