当前位置: 首页 > 科技观察

应用服务器内存溢出怎么办?两款工具帮你解决问题

时间:2023-03-15 10:32:11 科技观察

问题描述对于B/S架构的J2EE应用系统来说,应用服务器内存溢出(OutOfMemoryError)错误是一个非常棘手的问题。解决问题的关键在于定位问题。内存溢出的一般原因有:Jvm内存参数设置不合理,如:-Xmx设置比较小-Xms设置太大Sun的jvm没有设置-XX:MaxPermSize大小等参数引起的内存溢出设置问题往往很容易发现,调整参数,问题基本可以解决。应用服务器缺少必要的补丁。例如Websphere的某些版本存在很多性能缺陷,在某些情况下会出现内存溢出。打上补丁后,问题基本可以解决。应用程序代码中的缺陷是内存溢出最常见的原因,也是解决起来最麻烦的。本文主要介绍如何分析定位此类内存溢出问题。解决办法工欲善其事,必先利其器。有了好的工具,解决问题往往可以达到事半功倍的效果。很多时候,如果没有工具的支持,问题是很难解决的。本文主要涉及两个工具的使用:分析JavaCore的工具:IBMThread和MonitorDumpAnalyzerforJava。分析Heapdump的工具:EclipseMemoryAnalyzer。通过这两个工具,基本可以定位到一般的内存溢出问题。在介绍这两个工具之前,先解释一下相关的概念:Heapdump对Java进程内存在某一时刻进行快照,记录当时各个对象在内存中的存储和引用关系等。Heapdump中不包含对象的调用信息,即无法从Heapdump中看出是哪个程序代码产生了一个对象。JavaCore在某一时刻对Java进程中的线程进行快照,记录下所有线程在该时刻的执行栈信息。在JavaCore中可以看到每个线程在处理哪些程序代码,可以看到Java当前在做什么。在线程的执行栈中,有代码调用信息和对象生成相关信息。内存溢出的两种类型内存溢出一般分为两种,内存使用过多和内存泄漏。过度使用是指在短时间内快速消耗大量内存导致内存溢出。内存泄漏是指内存在很长一段时间内逐渐耗尽导致内存溢出,可能需要数小时或数天(通过启用详细的垃圾收集,可以清楚地观察到内存的分配情况)。Java系统中的内存溢出大部分是由于内存使用量过大造成的,内存泄漏比较少见。本文余下部分也是关于内存使用过多导致内存溢出的分析方法。对于内存使用过多导致的内存溢出,可以使用Heapdump和JavaCore来分析定位问题。对于内存泄漏,主要分析Heapdump。当Java进程出现内存溢出错误时,通常会生成Heapdump文件和JavaCore文件,比如Websphere部署的web应用。当发生内存溢出时,会在下面的目录/opt/IBM/WebSphere/AppServer/profiles/server1中出现这样的文件:Heapdump.*.phd文件记录Heapdump信息,javacore.*.txt记录JavaCore信息。一般内存溢出时会出现多个phd文件和JavaCore文件,可以取其中一个进行分析。下面将介绍如何通过工具对这两个文件进行分析,以及如何通过对这两个文件的分析来定位内存溢出(内存使用量过大引起)的原因。JCA),它以图形化的方式展示了java线程的堆栈信息和相互关系。下面是工具使用截图:对于Websphere,主要关注WebContainer线程的执行栈。上图是WebContainer:thread57的执行栈,Javacore文件本身是一个文本文件,也可以直接通过editplus等文本编辑器打开。下面是WebContainer:thread57用文本编辑器打开javacore文件后的执行栈:可以看到打开javacore和通过editplus打开javacore,没有本质区别,只是显示形式不同,具体使用关于JCA工具这里就不详细介绍了。分析javacore的要点就是根据各个线程的栈信息找出是哪个线程或哪些线程导致了java进程的内存溢出,对应线程栈中的代码段就是罪魁祸首。比如分析出WebContainer:thread57可能会导致内存溢出,那么57号线程中的这段代码就是问题所在。为什么WebContainer有问题:线程57而不是其他线程?这就需要结合heapdump进行综合分析,下面会详细介绍。2.分析HeapdumpHeapdump的分析工具推荐EclipseMemoryAnalyzer(简称MAT),它比IBM的HA(HeapAnalyzer)工具更强大也更易用。下面是该工具的截图:该工具可以看到对象占用内存的大小,对象的数量等信息。通过分析内存占比最大的对象,可以初步判断是哪个对象导致了内存溢出。MAT工具的具体使用这里就不详细介绍了。heapdump分析的重点是找到占用内存最大的“业务对象”。所谓业务对象就是与应用业务相关的对象,需要能够依赖于应用程序。比如上图,虽然java.lang.String比DicRestrict对象占用内存多,但是我们在分析的时候应该重点关注DicRestrict对象,因为String对象是一个通用的业务无关对象,很多业务对象可以引用它。Heapdump分析需要结合业务知识和相当多的开发和业务经验。3.单独分析两把剑合并Javacore和heapdump只看到了事情的一面。通过一定的方法将两者有机地结合起来,就可以基本解决问题。