问题现象:
平台导入大量数据,进行同步时。系统卡死无法使用、MQ消息大量堆积。查看后台发现,CPU占用高,出现内存泄露 FULL GC。
问题排查:
-
top指令,查看CPU占用率
-
jmap指令,抓取dump文件
jmap -dump:format=b,file=heapdump.hprof pid
-
工具:MemoryAnalyzer.ini
分析dump文件、查看占用内存的前几项分别是什么
-
修改之后:重新进行性能测试
解决思路:
-
优化代码
找到FULL GC的原因,针对性修复代码 -
扩大内存
修改配置文件中,JAVA自动内存相关配置参数,把内存值调大
具体原因
使用map类型的redis缓存,存储的数据量太大,产生了大key,反复调用,大量堆积,导致FULL GC。
根本原因
CPU飙升原因:
FULLGC会导致CPU飙升,通常用户线程是需要为GC线程让步的,所以GC线程会疯狂占用CPU,让其他线程都等待,导致所有功能不能正常运行。CPU飙升100%的时候,有线程在死循环
FULLGC原因:
对象分配到JVM的内存空间,是有分配策略的,比如:
(1)、大对象优先分配老年代
(2)、对象优先分配到年轻代的 Eden区,然后是 servicer1区,然后是老年代
(3)、老对象也会放到老年代
(4)、分配担保: 就是在年轻代的两个区都放不下的时候,就分配到老年代,如果老年代也放不下了,那么久进行fullGC
这个时候就会触发FullGC
FullGC 是会回收堆内存中所有地方的对象,回收了之后,程序继续判断 老年代是不是可以放下,
如果能,放下当前代放入的对象到堆内存
但是下次再进来的对象从年轻代问了一圈后,发现老年代也又满了,这个时候就再触发FullGCC,如此循环往复
垃圾回收这个线程 进入了死循环,一直抢占CPU资源,而且他是独占似的,这就造成了其他线程获取不到cpu,cpu利用率到达最高,所以飙升100%
另外一种,如果不能, 那么直接抛出OOM内存溢出错误