一、内存溢出现象
异常堆栈:
top 信息:
现象描述:
服务器发布/重启后,进程占用内存 21% 3g 左右,观察进程占用内存,以一天5%左右的速度增长,一定时间过后,java 进程内存增长到接近 90%,服务器报警。此时 old 区内存在 50%左右,由于未达到 CMS GC 的阈值,因此不会触发 CMS GC,而导致服务器内存溢出崩溃。
JVM配置:
8核16G
JVM 参数:
-Xms8g (初始化堆内存8g)
-Xmx8g (最大堆内存8g)
-Xmn3g (young 区3g)
-Xss512k (线程堆栈大小)
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:-UseGCOverheadLimit (不限制GC运行时间)
-XX:+DisableExplicitGC (不允许 System.gc())
-XX:+UseConcMarkSweepGC (ParNew+CMS+Serial Old收集器组合进行垃圾收集。Serial Old作为CMS收集器出现Concurrent Mode Failure的备用垃圾收集器。)
-XX:+CMSParallelRemarkEnabled (允许并发标记,针对 CMS 收集器)
-XX:+UseCMSInitiatingOccupancyOnly (通过 CMSInitiatingOccupancyFraction 进行每一次 CMS 收集)
-XX:+UseFastAccessorMethods (原始类型的快速优化)
-XX:CMSInitiatingOccupancyFraction=70 (old 区达到70%执行 CMS GC)
二、排查过程
1.异常堆栈分析
根据异常堆栈,可看出是因为调用 hbase.write()
分配直接内存导致的堆外内存溢出。
观察 JVM 参数,未设置直接内存大小参数: