堆内存泄漏

定位思路

Java程序异常崩溃或者响应慢,日志中有OutOfMemoryError:Java heap space关键字。定位思路如图1所示。

图1 堆内存泄露问题定位思路
  1. 根据报错日志、内存空间使用比例、GC活动,确定是OOM现象。
  2. 调大内存参数,验证是否为内存泄漏,如果调大内存后问题不复现,则暂时可排除为内存泄漏问题。
  3. jmap导出堆栈文件,结合对象调用栈进行分析。

    1. 分析大内存对象空间占用是否合理。
    2. 业务调用前后分别导出堆栈数据,对比对象内存占用,分析内存增长是否合理。

  4. 若代码存在问题,修改代码重新编译后,测试验证。
  5. 如果为非内存泄漏问题,则需继续定位是否为JVM问题。

案例:周期性添加string对象导致内存泄露

问题现象:

某Java进程出现运行缓慢,请求时延异常偏高的现象,且日志中能够查看到OutOfMoryError:Java heap space的异常。

定位过程:

  1. jstat命令查看GC活动,可以看到在频繁FullGC,且老年代内存使用率(O列)一直接近100%。

  2. 增大最大Heap内存后,重新运行业务,一段时间后,查看GC活动,依然处于满负荷状态。
  3. 使用jmap抓取内存,看到存在大量String对象。

  4. 使用jmap导出堆内存文件,并用jvisualvm工具载入继续分析,对怀疑点结合代码分析。

  5. 代码逻辑分析,该案例中Map对象周期性的添加数据,但是没有清除数据,基本可以确定问题出现在此处。

  6. 代码修改后编译并合入补丁到环境,验证问题得到解决。