# 内存溢出宕机分析步骤

# 一、如何判断是否内存溢出

# 通过查找内存溢出文件判断

  1. 非信创环境下,检查 ApacheJetspeed/bin 目录下是否存在类似 java_pid233380.hprof 名称的大文件,文件大小一般接近JVM最大堆内存。

  2. 信创环境下,可以检查 信创中间件的bin、logs目录下是否存在类似大文件。

  3. 如果部署了SeeyonDumpTools,可以到当天的dump日志目录下检查是否存在名为 _heapdump_20260410.bin 的大文件。

如果存在内存溢出文件,则文件生成时间存在内存溢出现象

# 通过检查堆内存年老代使用率判断

方法1: 登录OA系统管理员账号,切换后台,进入系统维护,系统监控。检查JVM堆内存老年代使用率

1778464126648.png

检查老年代使用率(Old Gen:Used Ratio)是否超过90%,超过则说明已经出现或内存溢出的风险很大。

同时关注峰值使用率(Peak Ratio),超过90%,也说明已出现内存溢出或风险较大。

方法2: 如果已部署SeeyonDumpTools工具,可以检查问题时间前后的dump日志:(oaStatus_xxxxx.htm)

该文件记录了每分钟的系统监控信息,同样可以帮助判断是否有内存溢出风险。

方法3: 如果OA服务已无法登录查看系统监控,但进程还没有结束。可以使用命令行的方式进行查看

登录OA服务器,进入 jdk/bin 目录下(注意必须有完整jdk,信创系统自带的jre没有相关工具,需拷贝完整jdk)

查找OA服务的进程号(PID),并执行以下命令

cd jdk/bin

# Linux
./jstat -gcutil 进程号

# Windows
jstat.exe -gcutil 进程号

查看"O"这一列,即是老年代使用率大小

同时结合"FGC"、"FGCT"这两列数据,来判断是否可能已经触发过 FullGC。

提示:老年代内存耗尽会触发Full GC。另外OA只会在每天凌晨主动调用一次System.gc(),此时FGC次数增加1次。

1775815600044.png

# 指标说明
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

# 二、如何分析内存溢出问题

# 方法1:分析内存dump文件

获取内存溢出文件

检查中间件下是否存在内存溢出文件。

手动导出内存dump

提示:需要在重启OA前才能导出。

由于JVM参数 -xx:+HeapDumpOnOutOfMemoryError 只会在内存彻底耗尽、程序即将崩溃(抛出OOM异常)的那一刻触发自动生成内存溢出文件。 所以很多时候内存耗尽触发 Full GC时,并没有主动生成.hprof内存溢出文件,就需要我们手动导出。

适用场景:堆内存老年代使用率(Used Ratio)大于85%,注意不是Peak Ratio。(峰值100%,当前使用率很低的情况导出没有用)

步骤:

  • 找出进程PID,命令:ps -ef | grep java
  • 到jdk/bin下执行命令导出内存dump
cd jdk/bin
# windows
jmap -dump:format=b,file=heap_2026_xx_xx.bin 进程PID
# Linux
./jmap -dump:format=b,file=heap_2026_xx_xx.bin 进程PID

注意:使用jmap导出内存dump期间,OA会无法访问请在执行前与客户沟通清楚。另外,导出所需时间受堆内存大小影响,如果OA完全无响应,则可能耗时非常久或无法完整导出。

分析内存dump文件

借助mat工具,可以分析内存dump文件或内存溢出文件。

# 方法2:借助工具分析堆内存适用情况

当已知JVM内存老年代使用率峰值很高,当前使用率又比较低(可能触发Full GC回收了),不适合手动jmap导,也没有内存溢出文件时。

1778466832094.png

此时可以借助部署内存火焰图或JFR分析

  • Linux系统使用内存火焰图(async-profiler-1.8.x)

  • Windows系统使用JFR(SeeyonDumpTools已集成:startdump.jcmd.jfr.bat(添加定时任务,每10分钟执行1次))

编撰人:wangyxyf