简单的内存分析

    在线上故障定位(尤其是OOM)和性能分析的时候,经常会用到一些文件来帮助我们排除代码问题。这些文件记录了JVM运行期间的内存占用、线程执行等情况,也就是我们常说的dump文件。常用的有Heap Dump和Thread Dump(也叫javacore)。

  • Heap Dump:它是一个二进制文件,保存了指定时刻的Java堆栈的快照,一种镜像文件。它反映了某时间点下JVM堆中对象的使用情况。
  • Thread Dump:它主要保存的是java应用程序中各线程在某一时间点的运行的位置,即程序执行到哪一个类的哪一个方法哪一个行上。thread dump是一个文本文件,打开后可以看到每一个线程的执行栈,以stacktrace的方式显示。
    通常,单个thread dump文件一般来说没什么用处,因为它只是记录了某一个绝对时间点的情况。比较有用的是,线程在一个时间段内的执行情况,所以两个thread dump文件在分析时特别有效。我们可以通过对thread dump的分析可以得到应用是否“卡”在某个点上,某个点运行时间太长,比如数据库查询,长期得不到响应。

    这里我们重点说一下,如何使用heap dump进行内存分析。

    首先,怎么获取到它呢?有三种方式:

  1. 使用JDK自带的jmap ①工具来触发,语法为:
    $JAVA_HOME/bin/jmap -dump:live,format=b,file=[dump文件名] [PID] ②
  2. 在应用程序启动时配置JVM参数 -XX:+HeapDumpOnOutOfMemoryError,当应用抛出OutOfMemoryError时自动生成dump文件
  3. 启用hprof功能。启动虚拟机时加入-Xrunhprof:head=site 配置,那么JVM会实时生成java.hprof.txt文件。但该配置会导致jvm运行非常的慢,不适合生产环境。

    那如果我们即没有配置JVM参数也未启用hprof功能呢?只能使用选用第一种方式了,这里我们重点说一下要怎么做。

    经常使用Linux系统的人知道,使用$JAVA_HOME的定位JDK的安装路径的前提是配置了环境变量$JAVA_HOME,如果没有配置(服务器环境现在通常都是没有配置的),那么就会出现如下情况:

    224725_GUuj_1474911.png

    如果使用which指令呢?首先你需要,which java定位到的是java程序的执行路径,并非安装路径。但是如果你仔细观察的话你会发现,which java 这个指令其实定位到了一个链接文件,它链接到的就是安装路径。所以我们可以这么做:

    230149_P6I0_1474911.png

    知道了$JAVA_HOME,通过jmap工具就能获取到dump文件了,那么现在dump文件有了,怎么解析它呢?解析heap dump有很多工具可以使用,比如IBM的HeapAnalyzer、JDK自带的jhat工具、Eclipse自带的MemoryAnalyzer插件,这里我们使用HeapAnalyzer。

    下载dump文件到Windows本地,IBM下载HeapAnalyzer工具,然后使用如下命令行的方式启动它:

java –Xmx[heapsize] –jar ha<HeapAnalyzer version>.jar <dump-file>

注意:

  • 如果dump文件不大的话,-Xmx参数可忽略
  • 可以忽略<dump-file>参数,先打开HeapAnalyzer,再File -> Open 导入dump-file文件

    界面如图所示:

    232036_KpTX_1474911.png

    查看Reference view视图或者打开Analysis -> Tree view视图,查看堆中对象的内存占比。显示的树状图按这种格式展示各个节点:

TotalSize(TotalSize/HeapSize%)[ObjectSize] NumberOfChildObject(Number of root objects) Name

  • TotalSize:资源总大小
  • TotalSize/HeapSize:堆内存占比
  • ObjectSize:对象大小
  • NumberOfChildObject:子类个数
  • Name Address:内存地址

    分析的主要思路是:堆内存占比越高,堆内存消耗越多。通过展开树状图的节点找到内存泄漏的地方,然后逐级向上排查,最后在应用程序中找到调用入口,而后分析程序,确定产生内存泄漏的原因。

 

注:

    ① 若要分析thread dump,可以使用jstack工具获取,语法如下:jstack [PID] > [dump文件名],则会将命令执行结果转储到指定的文件中

    ② 在JDK1.5时,语法为:jmap -heap:format=b [PID],在1.6中:live参数,表示是否指定存活的对象

转载于:https://my.oschina.net/duofuge/blog/1475731

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值