2010-07-26 73 views
3

我有JBoss上运行的J2EE项目,2048米的最大堆大小,这是给下负载测试奇怪的结果。我已经基准堆和CPU使用率并取得了以下结果(1系列是堆使用,系列2的CPU使用率):Java堆栈瓶颈 - 如何识别原因?

http://i29.tinypic.com/m9ul1e.png

看起来好像堆被正确并获得使用垃圾但是,当它到达B时,由于存在可用的堆空间,似乎存在某种瓶颈,但它不会中断该虚拟线。与此同时,在C处,CPU使用率急剧下降。在此期间,我们还收到“OutOfMemoryError(超出GC开销限制)”,由于存在可用堆空间,因此对我来说没有多大意义。

我的猜测是有某种瓶颈,但究竟我甚至无法想象。你会如何建议找出问题的原因?我分析了内存使用情况并注意到有一个类的实例(大约一百万),但这些实例的总大小相当小(如果我没有记错的话,大小约为50MB)。

编辑:服务器专用于此应用程序,给出的CPU使用率仅适用于JVM(JVM之外不应有任何重要的CPU使用率)。内存使用情况仅适用于堆,它不包含permgen空间。这个问题是可重现的。我主要关心的是围绕B遇到的限制,对此我还没有找到合理的解释。

结论:原来,这是由一堆长时间运行的SQL查询并发调用引起的。返回的结果集也非常大,可能解释了OOME。我仍然有为什么会出现显然有些限制在B.

回答

2

从它出现的JVM使用的垃圾收集并行算法清道夫错误消息没有合理的解释。当a lot of time is spent on GC, but not a lot of the heap is recovered时,该消息随OOMO错误一起丢弃。

来自Sun该文献没有指定如果所消耗的总时间的98%将被读取作为该过程的CPU利用率98%或CPU本身的。在任一情况下,我已经得出以下推论(具有有限的信息):

  • 垃圾收集器或JVM过程不具有足够的CPU利用率,最可能是由于其它处理的同时消耗CPU。
  • 垃圾收集器没有足够的CPU利用率,因为它是一个低优先级的线程,而另一个存储在JVM密集的(但不是CPU密集型)线程在同一时间在做的工作,从而导致未能去分配内存。

根据上述推论(全部,其中一个或全部都不是真),将用户关心的图形与应用程序的运行时行为关联起来是值得的。换句话说,您可能会发现确定是否启动了其他进程(发生问题时)或正在运行的应用程序的部分(再次出现问题时)会很有用。

在任何情况下,上面提到的网页,确实给了一个选项来禁用由GC算法使用的GC开销限制。如果问题周期性发生并且可以被重现,那么可能会导致内存泄漏,否则(即偶尔出现),您最好调整GC算法甚至更改它。

+0

第一个要点对我来说没有意义,因为CPU使用率下降。第二个似乎是合理的,但我仍然不明白为什么内存使用似乎达到了某种它无法通过的最大值?我宁愿不改变GC的开销限制,因为我有一种感觉,它只会解决症状而不是原因。 – Zecrates 2010-07-26 18:38:03

+0

如果您的图只报告JVM的CPU使用情况,而不报告其他进程,则第一点是有意义的。至于GC开销限制上的标志,那么只是禁用开销;你不能改变它。回到第二点,如果你能确定你是否达到高水位标准,这可能会有所帮助。我的意思是说,图很可能不是描述整个堆,可能只是它的一部分(它是否也包括permgen?)。 – 2010-07-26 18:54:09

+0

好的,我明白你说的第一点是什么意思。此图仅用于JVM的CPU使用情况,系统专用于此应用程序。该图不包含permgen,那么你是否暗示它可能是导致OOME的permgen空间?什么会影响permgen空间,过去我遇到的唯一问题是permgen的加载和卸载问题? – Zecrates 2010-07-27 06:24:51

0

如果我想知道“瓶颈”在哪里,我只是得到一些stackshots。没有必要怀疑和猜测,并扮演侦探。他们只会告诉你。

通常,内存问题和性能问题是并存的,所以如果你修复了性能问题,你也将修复内存问题(虽然不是一定的)。