性能测试总结之内存泄露和内存溢出(2)

发表于:2011-09-23来源:未知作者:领测软件测试网采编点击数: 标签:性能测试
Code Cache (non-heap):HotSpot Java虚拟机包括一个用于编译和保存本地代码(native code)的内存,叫做代码缓存区(code cache) 第三部分 监控(工具发现问题) 谈到内存监

  Code Cache (non-heap):HotSpot Java虚拟机包括一个用于编译和保存本地代码(native code)的内存,叫做“代码缓存区”(code cache)

  第三部分 监控(工具发现问题)

  谈到内存监控工具,JConsole是必须要介绍的,它是一个用JAVA写的GUI程序,用来监控VM,并可监控远程的VM,易用且功能强大。具体可监控JAVA内存、JAVA CPU使用率、线程执行情况、加载类概况等,Jconsole需要在JVM参数中配置端口才能使用。

  由于是GUI程序,界面可视化,这里就不做详细介绍,

  具体帮助支持文档请参阅性能测试JConsole使用方法总结:

  http://www.taobao.ali.com/chanpin/km/test/DocLib/性能测试辅助工具-JConsole的使用方法.aspx

  或者参考SUN官网的技术文档:

  http://Java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html

  http://Java.sun.com/javase/6/docs/technotes/tools/share/jconsole.html

  在实际测试某一个项目时,内存出现泄露现象。起初在性能测试的1个小时中,并不明显,而在稳定性测试的时候才发现,应用的HSF调用在经过几个小时运行后,就出现性能明显下降的情况。在服务日志中报大量HSF超时,但所调用系统没有任何超时日志,并且压力应用的load都很低。经过查看日志后,认为应用可能存在内存泄漏。通过jconsole 以及 jmap 工具进行分析发现,确实存在内存泄漏问题,其中PS Old Gen最终达到占用 100%的占用。如图所示:

内存泄露

  从上图可以看到,虽然每次Full GC,JVM内存会有部分回收,但回收并不彻底,不可回收的内存对象会越来越多,这样便会出现以上的一个趋势。在Full GC无法回收的对象越来越多时,最终已使用内存达到系统分配的内存最大值,系统最后无内存可分配,最终down机。

  第四部分 分析

  经过开发和架构师对应用的分析,查看此时内存队列,看哪个对象占用数据最多,再利用jmap命令,对线程数据分析,如下所示:

  num #instances #bytes class name

  ———————————————-

  1: 9248056 665860032 com.taobao.matrix.mc.domain.**

  2: 9248031 295936992 com.taobao.matrix.**

  3: 9248068 147969088 java.util.**

  4: 1542111 37010664 java.util.Date

  前三个instances不断增加,指代的是同一个代码逻辑,异步分发的问题,堵塞消息,回收多次都无法回收成功。导致内存溢出。

  此外,对应用的性能单独做了压测,他的性能只能支撑到一半左右,故发送消息的TPS,应用肯定无法处理过来,导致消息堆积,而JAVA垃圾回收期认为这些都是有用的对象,导致内存堆积,直至系统崩溃。

  调优方法

  由于具体调优方法涉及到应用的配置信息,故在此暂不列出,可以参考性能测试小组发布的《性能测试调优宝典》

  第四部分 总结

  内存溢出主要是由于代码编写时对某些方法、类应用不合理,或者没有预估到临时对象会占用很大内存量,或者把过多的数据放入JVM缓存,或者性能压力大导致消息堆积而占用内存,以至于在性能测试时,生成庞大数量的临时对象,GC时没有做出有效回收甚至根本就不能回收,造成内存空间不足,内存溢出。

  如果编码之前,对内存使用量进行预估,对放在内存中的数据进行评估,保证有用的信息尽快释放,无用的信息能够被GC回收,这样在一定程度上是可以避免内存溢出问题的。

原文转自:http://www.ltesting.net