JNI申请的native内存不受JVM管控。
一般建议 parallel scavenge (JDK8默认GC),适用大部分场景。
GC日志组成: GC时间, GC原因, GC位置(年轻代, 老年代, 元空间), 释放内存大小, 持续时间。
原则上, 优先看Full GC的频率, 其次查看日志STW阶段(比如G1里标记了pause, CMS里mark和remark)阶段消耗时间,
最后查看内存收缩情况。
用JMap工具可以转储Java堆到快照文件,然后用MAT工具分析,只要是堆内问题,就用MAT工具。
现象:
分析与解决:
1. 根据OOM错误提示,由于配置原因导致Java堆或者Metaspace区域oom,
判断标准之一是程序是否稳定运行,实际内存占用有升有降。
2. Metaspace本身没有限制,如果设置了MaxMetaspaceSize,则受限这个配置。
3.如果内存持续增长超出业务实际可能使用的内存量,则可能存在内存泄漏。
内存泄漏位置判断
1. 通过异常日志提示,
eg, Java.lang.OutOfMemoryError: Java heap space,
Java.lang.OutOfMemoryError: metadata space,
Java.lang.OutOfMemoryError: Direct buffer space,
2. 开启NMT(启动参数上加上 -XX: NativeMemoryTracking=detail), 可帮助判断那块内存区域内存泄漏。
堆内内存泄漏排查
1. 只要是Java堆或Metaspace区域内存泄漏,都可以转储Java堆快照文件,用MAT工具分析。
2. 多维度分析堆内对象分布,查找可疑内存最大占比的对象。
3.分析对象依赖路径,查找未释放原因。
堆外内存泄漏排查
1. 首先通过上文手段判断内存泄漏位置。
2.根据位置对应的功能,进一步查找具体的异常代码。
3. JNI申请的native内存本身已超出JVM控制范围,没办法用JVM工具排查。
借助操作系统工具pmap排查,可查看进程内存映射,查找可疑内存。
案例分析
例一.
某业务发现cpu值偶尔飙升,排查发现GC停顿较长。
进一步发现大量存活对象有些异常,怀疑内存泄漏。
最后heap dump 后使用MAT分析,发现一全局HashMap持有了大量重复对象,
业务代码里移除操作由问题,实际未移除,修复后问题解决。
例二.
某业务线迁移OSGI框架后,JVM无法响应外部