内存溢出分析

上一篇 / 下一篇  2012-06-26 10:47:09 / 个人分类:java

引用:http://developer.51cto.com/art/201203/321424.htm

1、介绍

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:

jstack [-l] pid

如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

2、命令格式

jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP

3、常用参数说明

1)options: 

executable Java executable from which the core dump was produced.

(可能是产生core dump的java可执行程序)

core 将被打印信息的core dump文件

remote-hostname-or-IP 远程debug服务的主机名或ip

server-id 唯一id,假如一台主机上多个远程debug服务 

2)基本参数:

-F当’jstack [-l] pid’没有相应的时候强制打印栈信息

-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.

-m打印java和native c/c++框架的所有栈信息.

-h | -help打印帮助信息

pid 需要被打印配置信息的java进程id,可以用jps查询.

二、我的使用场景

用spring3写了个小工具,经常报内存溢出

1、在tomcat的\bin\catalina.sh文件里添加

set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

2、后来还是偶尔会溢出就想查看下具体原因,所以采用了jstack

(1)、打开任务管理器,查看java.exe的pid(220)

(2)、运行cmd,然后输入jstack -l 220 得到结果


"schedulerFactory_Worker-2" prio=6 tid=0x037fc800 nid=0x9b4 runnable [0x0403e000..0x0403fa94]
   java.lang.Thread.State: RUNNABLE
        at com.mysql.jdbc.TimeUtil.fastTimestampCreate(TimeUtil.java:1134)
        at com.mysql.jdbc.ResultSetImpl.fastTimestampCreate(ResultSetImpl.java:1030)
        - locked <0x0bd4b1e0> (a com.mysql.jdbc.JDBC4ResultSet)
        at com.mysql.jdbc.ResultSetRow.getTimestampFast(ResultSetRow.java:1310)
        - locked <0x0bd166e8> (a java.util.GregorianCalendar)
        at com.mysql.jdbc.ByteArrayRow.getTimestampFast(ByteArrayRow.java:124)
        at com.mysql.jdbc.ResultSetImpl.getTimestampInternal(ResultSetImpl.java:6617)
        at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:5943)
        at com.mysql.jdbc.ResultSetImpl.getTimestamp(ResultSetImpl.java:5981)
        at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.ibatis.common.jdbc.logging.ResultSetLogProxy.invoke(ResultSetLogProxy.java:47)
        at $Proxy15.getTimestamp(Unknown Source)
        at com.ibatis.sqlmap.engine.type.DateTypeHandler.getResult(DateTypeHandler.java:38)
        at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getPrimitiveResultMappingValue(BasicResultMap.java:611)
        at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicResultMap.java:344)
        at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:381)
        at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:301)
        at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:190)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:205)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)
        at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForList(GeneralStatement.java:123)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:615)
        at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:589)
        at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:118)
        at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMapClientTemplate.java:295)
        at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMapClientTemplate.java:1)
        at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:200)
        at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClientTemplate.java:293)
        at com.taobao.web.app1.dao.impl.LogMessageDaoImpl.getLogMessageList(LogMessageDaoImpl.java:19)
        at com.taobao.web.app1.service.impl.LogMessageServiceImpl.getLogMessagesById(LogMessageServiceImpl.java:37)
        at com.taobao.web.app1.action.TimeAction.insertSql(TimeAction.java:32)
        at sun.reflect.GeneratedMethodAccessor52.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
        at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:264)
        at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)

从而找到了内存溢出点,是一次往内存里读取了一千万多条数据,,额的神啊。。。。。

二、后来发现这个方法不是很管用,得到的jstack文件看不出问题,这时候,设置下Tomcat,使其在OOM时打印出dump数据。

%tomcat%/bin/catalina.sh

中set JAVA_OPTS=-Xms256m -Xmx256m

后添加-XX:+HeapDumpOnOutOfMemoryError

如果有OOM则会dump数据到%tomcat%/bin目录下

然后用MAT来查看数据,用法见:http://zheng12tian.iteye.com/blog/1676715

TAG:

 

评分:0

我来说两句

Open Toolbar