中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

调优过程

前提条件

  • 服务器和操作系统正常运行。
  • PC端已经安装SSH远程登录工具。
  • 已准备需要优化的Java程序(demo)。

准备工作

  1. 登录Java性能分析工具。
  2. 添加目标服务器(待分析的Java进程所在服务器)。
    图1 添加目标环境
  3. 启动在线分析功能。
    图2 启动在线分析

在线分析

  1. 概览页签查看进程整体情况。
    图3 概览

    通过概览页面发现程序的堆使用情况在一段时间内不断升高,同时GC也比较频繁,但是堆却没有明显的被释放,可能存在内存泄露。

  2. GC页签查看GC详情。
    图4 GC页签

    分析发现GC比较频繁的有YoungGC和OldGC,但是每次GC回收的内存可以忽略不计,甚至根本没有回收任何内存,此现象说明内存泄露的可能性很大。

  3. 内存页签查看内存详情。
    图5 内存页签

    在内存转储页签下点击执行内存转储按钮生成堆转储文件,为了方便查看堆的变化可以保存快照,生成多次堆转储文件。

  4. 再次生成内存转储。
    图6 结果比较

    通过生成两次堆转储文件发现TestMemoryLeak$Person这个类应该是自定义的类,内存占用情况比较多,并且随着时间呈上升趋势,需要重点观察。

    可以利用快照功能提供的比较操作,方便查看两个堆转储文件中相同类实例与保留堆的变化情况,通过比较发现TestMemoryLeak$Person实例与保留堆是明显上升的趋势。

  5. 切换模式查看。
    图7 支配树视图

    切换到支配树模式,发现TestMemoryLeak 类的保留堆占总堆的比例高达 99%,继续向下点开支配树发现大部分对象是 TestMemoryLeak$Person 持有的 byte[],到这里正好可以跟直方图中byte[] 占比较多可以对应的上。

  6. 结果分析。
    图8 代码片段

    经过直方图与支配树的分析,TestMemoryLeak$Person类对应的实例有内存泄露嫌疑,根据支配树提供的内容应该是 HashSet 实例持有TestMemoryLeak$Person对象,接下来咱们可以搜索代码中的相关项看看。本案例中的demo 程序比较简单,直接搜索TestMemoryLeak类可以发现的确存在内存泄露点,一个线程不断的往hashSet和hashSetPerson两个静态对象添加 Person 实例,并且没有清除的逻辑,导致出现内存泄露。

采样分析

对目标程序进行采样分析,最好进行多次采样,采样时间相对长一点。

  1. 启动采样分析。
    图9 配置采样分析参数
  2. 查看采样分析结果。
    图10 采样分析结果