转自 http://121.32.28.234:8800/kdwiki/index.php?doc-view-121.html
主要是为了自己学习HeapDump的分析,这是一篇好文章。
场景描述: EAS服务器运行一段时间后,客户端与portal登陆时,出现内存溢出的错误。有时甚至出现服务器直接宕机了,管理控制台也启动不了,客户端与portal都连接超时,必须使用EAS自带的stopserver.sh命令去终止服务器再重启。
解决思路:
内存溢出后,到EAS服务器目录:eas\server\profiles\server*\bin下,看是否有类似:heapdump.20110718.120928.3804.0010.phd和Javacore*.txt的文件生成。(注:默认情况下,如果使用sunjdk内存溢出时是不自动生成此类文件的,只有用ibmjdk才会自动生成。)如果没有找到此类文件,请切换EAS服务器使用ibmjdk,重启服务器后继续观察。(具体切换步骤请看附录2)。
ØHeap Dump:JVM内存Dump(HeapDump文件)。通过对它的分析可以快速诊断导致内存消耗的原因。Heapdump文件包含了在堆内存中的所有对象,可以理解为系统发生内存溢出(OutOfMemory,即OOM)时堆内存的快照。
ØJavacore:与heapdump对应的线程堆栈信息,一般通过对它的分析可定位到发生内存溢出的功能点。
ØHeap Dump分析工具:Heap Analyzer 下截地址:http://www.alphaworks.ibm.com/tech/heapanalyzer/download
一般情况下,解析heapdump文件需要64位的jdk,并要求机器内存>=4G。因此一般都需要用客户的测试服务器或服务器上进行解析,普通的PC机完成此项任务。
Ø工具准备好后,可到命令行下启动Heap Analyzer工具。
命令如下:C:\Kingdee7\eas\jdk\bin\java -Xmn512m –Xmx4000m -jar ha414.jar
(如果解析过程中内存溢出,可跟据实际情况调大–Xmx这个参数)
Heap Analyzer工具打开后,点击以下图标选择打开heapdump文件:
1、打开heapdump文件会消耗系统的CPU、内存资源,系统性能会有所下降。建议尽量不在客户正式环境执行!如果实在没有其他机器,正式环境资源充足,且问题比较紧急,可以尝试使用正式环境。打开分析完后及时关闭以释放资源。
2、在打开过程中,出现如下图形,说明工具设置的最大内存不够,不能打开该文件,需采用ibm jdk来设置更大的最大内存来打开
Root object:没有任何一个对象引用(持有)它
Parent object:对象A引用X,引用Y等(A—>X , A—>Y…),A就是父对象
Child object:对象X被A引用,被B引用等(A—>X , B—>X…),X就是子对象。
Owner object:因为子对象可能被多个父对象引用,但只能为其中一个父对象所有,这个父对象就是Owner object。Total size的计算会涉及到Owner object,这是为了避免重复计算
Size :对象自身的大小(持有该对象的指针在内存中占用的大小)
Total Size:对象自身及子对象的和
1,界面打开后初始状态如下,主要对tree view这个视图进行分析,可最大化这个视图
2 、tree view中每一行的结构如下:
TotalSize(占用总内存百分比)[对象自身大小]子对象个数对象名称内存地址
3、泄漏一般发生在那些拥有“超乎寻常多”的引用(子节点)的class上,正是这些创建后没有释放、累积了成千上百的对象,造成了OutOfMemory。通过“Locate a leak suspect”和“Go to the largest drop in subtrees”可快速定位到子对象多的对象位置。
4、通过“show from roots”可以回到根节点
5、 通过“List same type”可以列出所有在内存中和该对象相同类型的对象。
步骤2 右键展开上图中LRUMap对象,如下
步骤 3 对上图中的RowSetSqlDec对象右键点“List same type”,可看到该对象有3001个,共占用了700多M内存:
主要内存占用在如下三个部分
展开上述内存占用
与调拔入库单相关的对象(分录)占用了2百多兆
还是与库存相关的对象(单据头)相关占用1百多兆
与调拔入库单相关的对象共占用4百多兆内存,
分析javacore文件(用dump文件中的看到的关键字MoveInWareBill来搜索),摘取的线程堆栈如下:
at java/lang/String.toLowerCase(String.java:1143(Compiled Code))
at com/kingdee/eas/scm/common/app/AbstractSCMBillBaseControllerBean._getCollection(AbstractSCMBillBaseControllerBean.java:181)
at com/kingdee/eas/scm/im/inv/app/AbstractInvBillBaseControllerBean._getCollection(AbstractInvBillBaseControllerBean.java:174)
at com/kingdee/eas/scm/im/inv/app/AbstractMoveInWarehsBillControllerBean._getCollection(AbstractMoveInWarehsBillControllerBean.java:173)
at com/kingdee/eas/scm/im/inv/app/AbstractMoveInWarehsBillControllerBean.getMoveInWarehsBillCollection(AbstractMoveInWarehsBillControllerBean.java:161)
at com/kingdee/bos/transaction/EJBTxFacade/TxInvokerBean_LocalObjectImpl_2.INVOKE_SUPPORTS(Bytecode PC:4(Compiled Code))
at $Proxy591.getCollection(Bytecode PC:22)
at com/kingdee/bos/framework/DynamicObject.invoke(DynamicObject.java:57(Compiled Code))
at com/kingdee/bos/framework/DynamicObject.getCollection(DynamicObject.java:246)
at com/kingdee/eas/base/dap/app/DAPAppTools.execDataFilterMultiEntry(DAPAppTools.java:75(Compiled Code))
at com/kingdee/eas/base/dap/app/DAPTransformerControllerBean._innerTransform(DAPTransformerControllerBean.java:1028)
at com/kingdee/eas/base/dap/app/DAPTransformerControllerBean._transformForBotp(DAPTransformerControllerBean.java:1131)
at com/kingdee/eas/base/dap/app/DAPTransformerControllerBean._transform(DAPTransformerControllerBean.java:813)
at com/kingdee/eas/base/dap/app/DAPTransformerControllerBean._generateVoucher(DAPTransformerControllerBean.java:649)
at com/kingdee/eas/scm/common/app/SCMBillBaseControllerBean._generateVoucher(SCMBillBaseControllerBean.java:1057)
通过线程堆栈可以看出:调拔入库单生成凭证内存占用过大,导致溢出宕机
附录2:如何切换EAS的运行时环境?
在eas\server\profiles\server*\bin目录下,找到set-server-env.bat(sh)文件。将JAVA_HOME变量的值设置为imbjdk的路径。如果找不到JAVA_HOME这个变量,请直接添加。如下图: