JAVA内存分析指引201007_V0.2

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JA V A内存分析指引

2010-07

1 环境说明

根据一般项目部署情况,生产环境以WebSphere5和WebSphere6为主,本文中所涉及环境变量也主要采用WebSphere的相关环境变量。

WebSphere5安装目录(默认):

Windows:C:\Program Files\WebSphere\AppServer

AIX:/usr/WebSphere/ AppServer

WebSphere5日志路径

Windows:C:\Program Files\WebSphere\AppServer\logs\server1

AIX: /usr/WebSphere/ AppServer/logs/server1

WebSphere6安装目录(默认):

Windows:C:\Program Files\IBM\WebSphere\AppServer

AIX:/usr/IBM/WebSphere/AppServer

WebSphere6日志路径:

Windows:C:\Program Files\IBM\WebSphere\AppServer\profiles\AppSrv01\logs\server1

AIX: /usr/IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1

2 内存溢出原理

内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。

为了解决Java中内存溢出问题,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的。

Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。GC为了能够正确释放对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

在Java中,这些无用的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。虽然,我们有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java 语言规范定义,该函数不保证JVM的垃圾收集器一定会执行。因为不同的JVM实现者可能使用不同的算法管理GC。同时JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。

若GC连续回收不能解决内存堆不足的问题时,就会报out of memory 错误。

PS:显示调用System.GC() 只能建议JVM 需要在内存中对垃圾对象进行回收,不能马上对内存进行回收。需慎用System.GC(),一个是并不能解决内存资源耗空的局面,另外频繁调用也会增加GC对内存的消耗。

3 内存溢出现象

在WebSphere的日志路径下的SystemOut.log日志文件中会出现如下异常信息,系统的可用内存和性能持续下降,最终导致应用服务器系统down掉,不能响应任何请求。

当出现内存溢出时,在IBM WebSphere平台,如果在性能诊断顾问程序配置里面选中了"启用自动堆转储收,在WebSphere的安装目录下(WebSphere6在%安装目录%\profiles\ AppSrv01下)将会生成javacore*、heapdump*之类的文件。其中,javacore文件记录cpu线程相关信息,heapdump文件记录内存使用信息。

4 内存溢出原因

内存溢出主要有以下四个方面的原因:

1)内存中加载的数据量过于庞大。

案例一:在我们的项目中很多都用到了Excel导出功能,当一次导出的数据量过大时可能出现内存溢出的情况。

案例二:在查询数据时,如果查询的数据量过于庞大,也可能会导致内存溢出的情况。一般可以考虑通过分页机制来减少每次数据加载量。。

2)在代码中出现死循环和死递归

3)JVM的内存值设置过小。生产环境一般建议初始值512M,最大值1024M。最好不要

超过1.5G

4)集合类和数组的使用不规范,存在对象的引用未消除,导致JVM不能回收或内存泄

露的情况。

5 内存溢出分析与诊断

内存分析与诊断一般步骤:

检查JVM参数配置->检查系统日志->收集内存溢出信息->代码走查->内存工具分析5.1检查JVM参数配置

检查WAS配置的JVM启动内存参数,确认该参数是否配置合理。在一些项目中由于本身的业务逻辑复杂,需要较大的内存开销,而内存参数设置过小,导致内存溢。

WAS配置方法:

应用程序服务器> server1 > 进程定义> Java 虚拟机,将最大堆大小(默认为256M)修改为一个合理的值,一般设为1024M,最好不要超过1.5G。

PS:在配置该参数时不能盲目的配置,如果配置过小,JVM的GC过于频繁,开销过大导致系统运行缓慢,内存溢出的概率会较大。如果配置过大,JVM在GC的时候,耗费时间过长。也会影响系统的性能和使用效果。

5.2检查错误日志

检查WebSphere日志路径下的SystemOut.log和SystemErr.log文件。查看在出现“OutOfMemory”错误前是否有其它异常或错误。

对于前面所描述程序上的一些死循环、死递归的BUG可以很快根据抛出的异常信息进

行定位。

例如在EHR的动态报表系统,一个构造指标树的程序中,由于没有控制指标选择,在树的节点上出现了相同的ID的同一个指标,因致死递归导致内存溢出使系统宕机。

通过在指标选择时加以控制,不让添加重复指标,解决了内存溢出的错误。

查看日志对于分析内存溢出是非常重要的,通过仔细查看日志,分析内存溢出前做过哪些操作,可以大致定位有问题的模块。

5.3收集内存溢出信息

WAS中自带了一些内存泄漏的探测工具,启动这些工具WAS就可以对内存溢出发生警报。例如:

1)性能诊断顾问,可以将输出信息显示在WebSphere的管理控制台,并记录在WebSphere应用服务器的SystemOut.log日志文件里面。

2)启用JVMTI,可以使用PMI 定制选项来启用所选统计信息以收集特定数据。在WebSphere应用服务器的日志目录下,native_stderr.log文件就是内存回收分析文件。

PMAT工具解析JAVA SDK的详细内存回收(GC)日志,并提供统计信息,图表,分析并推荐Java堆配置。PMAT提供了丰富的图形界面来显示Java堆的使用状况,从而更轻松地判断是否有内存问题发生。

3)启用自动堆转储收集,可以自动在WebSphere profile所在的路径下生成heapdump 文件。可以使用IBM HeapAnalyzer、MDD4J等内存泄露分析工具对heapdump文件进行分析。显示主内存转储中Java 堆占用量的主要组成部分的拥有关系上下文图,根据对对象引用图执行的深度优先遍历,用树形视图显示主内存转储的所有内容。

这是我们比较常用的分析内存溢出的方法。

5.4代码走查

对代码进行走查和分析,找出可能发生内存溢出的位置。重点排查以下几点:

1)检查代码中是否有死循环或递归调用

2)检查是否有大循环重复产生新对象实体。

3)检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。对于数据库查询建议尽量采用分页的方式查询。

4)检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象

相关文档
最新文档