点击上方 "Java指南者"关注, 星标或置顶一起成长

免费送 1024GB 精品学习资源

来源:https://zhanghan.blog.csdn.net/article/details/109255980

前言

最近刚上线了一款社交项目,运行十多天后(运营持续每天推量),发现问题:

  • 系统 OOM(资源不能被释放)导致服务器频繁且长时间 FGC 导致服务器 CPU 持续飚高
  • 日志中内存溢出:java.lang.OutOfMemoryError: Java heap space
  • 程序十分卡顿,严重影响用户使用

从以下方面,为大家分享此次问题解决流程

  • 问题出现现象
  • 临时解决方案
  • 复现问题
  • 定位问题发生原因
  • 优化代码
  • 优化后进行压测,上线
  • 复盘

学完本博文,你的收获

  • 排查内存溢出的思路
  • 排查内存溢出过程中用到的命令及工具(Linux 命令,Eclipse Memory Anaylzer[MAT])
  • 定位系统内存溢出的代码,并进行优化
  • 此次内存溢出问题复盘
  • 解决方案流程图

问题&临时解决方案&定位问题&最终解决方案

问题:

  • 业务反馈程序用的十分卡,同时测试自己测的也十分卡

  • 从 ELK 收集的请求日志发现确实存在问题,线上是两台部署:两台机器上都是,一次请求耗时由原来的几毫秒变为 10 几秒

  • CPU 跑的过高,当时是 4 核,CPU 持续飙到 350%+;

  • 当时一台服务器 CPU 截图:


临时解决方案

  • 当时为了减少对业务影响,直接将生产两台服务器上的项目进行重启
  • 项目启动参数中没有加内存溢出日志输出(后续博客为大家介绍 JVM 调优时讲解启动命令中加内存溢出日志输出),重启后出问题时项目的 JVM 信息丢失了

复现问题方式:在开发环境对程序进行持续压测;压测相关服务器配置:

  • 服务器配置:8 核,16G

  • 项目启动内存:136M

  • Jmeter 持续(循环)压发消息接口 10 分钟

定位问题

top 命令查看最耗 CPU 的进程(进程:17038;CPU 持续飙到 595%+)

# 输入top命令后键入P(大写P),进程按照CPU从高到底排序top


  • 查看该进程中最耗 CPU 的线程(发现有一些线程占用 CPU 较高)
17038为进程号,键入P(大写P),该进程中的线程按照CPU从高到底排序top -Hp 17038

  • 将线程号转为 16 进制,同时查看这些线程当前正在干什么(在此以 17045 线程为例
# 将线程号转为16进制;其中17045为线程号printf '%x\n' 17045# 17038为进程号,0x4295为最耗CPU线程的十六进制jstack 17038 | grep '0x4295' -C10 --color

  • 可以看到最耗 CPU 的线程都是在进行 GC

  • 用 Jmap 命令查看当前堆的使用情况(发现老年代现在已占用 99.8%+)

# 其中17038为进程号jmap -heap 17038

  • 查看 gc 频率的命令(其中 O 代表老年代占用率,FGC 是 FullGC 次数,FGCT 是 fullGC 时间;可以看出在频繁 FullGC 但是老年代有资源一直释放不掉)
# 其中17038为进程号,5000是指每5秒(5000毫秒)输出一次jstat -gcutil 17038 5000

  • 通过分析出问题时线上日志发现内存溢出;至此定位到问题根源是内存溢出导致(有未释放资源堆积,导致老年代被占满,然后频繁的 FullGC 但是资源一直释放不了)
grep -m 10 'OutOfMemoryError' *.log


分析问题产生原因

  • 由于线上当时直接重启,未能保留当时的 JVM 内存文件;在开发环境进行循环压测,复现线上问题,然后导出 dump 文件进行分析找到原因

  • 生成 dump 文件命令

# 其中fileName是导出后dump名称,pid为进程号jmap -dump:format=b,file=fileName.dump pid12
  • 将 dump 文件导出到本地,用 Eclipse Memary Analysis(MAT 官网下载地址) 进行分析

  • MAT 导入 dump 文件



  • 按对象排序视图进行查看(总览中看到对象总个数:14.1 百万个)

  • 发现有两个类(ClassClassPath,ClassClassPathList)占用比较大,这两个类约占对象总数的 83%(计算方式:5873361*2/14100000=83%)

分析代码

  • 去代码中全局搜这两个类,发现只有在打日志的时候用到 ClassClassPath 类

分析 ClassClassPath 相关代码:

  • 用到 ClassClassPath 对象是一个静态的 ClassPool;

  • 问题原因:classPath 一直被静态的全局 pool 所持有,导致 GC 一直释放不掉;





  • 当然顺着代码,顺藤摸瓜也找到了 ClassPathList


  • 优化代码:每次用完 ClassClassPath 后将其释放

  • 每次对象使用完后从静态 pool 中移除

  • 注意:classPath=null 这种方式是不能释放掉的


优化后再次进行验证

  • 开发环境循环压测,用 MAT 分析 dump 文件,发现内存中已不再堆积 ClassClassPath 类;优化前后接口吞吐量也提升 8.2%
  • 进行线上发布,观察一周后,对内存分析发现正常

复盘:

项目比对:

  • 为快速开发,社交的代码从原来金融项目基础上改造而来;

  • 原来金融项目没有内存溢出,而社交项目为什么内存溢出?

  • 通过 ELK 统计一段时间的访问量结果:

    • 社交目前日访问后台量 65w+
    • 金融项目只有 4.5W+
  • 社交和金融项目业务类型不一样,所呈现出的特点也不同

  • 去生产的金融项目中 dump 内存文件,用 MAT 工具分析,发现也存在 ClassClassPath 类堆积释放不掉,只不过由于访问量少,堆积量未占满老年代而已;果断在金融项目迭代时将其优化;

  • 程序预警:为减少业务影响,增加接口耗时的预警(后续博文为大家共享);实现方式:

  • 在每次程序处理完进行预警(比如本次请求>阈值);缺点:消耗性能影响正常业务

  • 在 ELK 清洗时用相关插件进行预警;优点:和业务解耦,对业务无影响

  • 服务器预警:运维增加 CPU 内存,日志内存溢出监控

总结

解决内存溢出过程总结:

  • 不同的项目导致内存溢出原因是不同的;

  • 重要的是排查思路

  • 经过不断的耐心的去观察,测试,分析才能定位到问题并最终解决问题

在这次分析内存溢出过程中,我们也针对我们项目的 JVM 启动参数进行了调优,在接下来的博文中为大家分享 JVM 调优


热门内容:

两年经验斩获蚂蚁/头条/PingCAP Offer,牛逼了

字节跳动热腾腾的面经分享深入理解 Java 内存模型

关注我

关注我,Java 学习不迷路!


jprofiler分析dump文件_内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)...相关推荐

  1. 内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)

    前言 最近刚上线了一款社交项目,运行十多天后(运营持续每天推量),发现问题: 系统OOM(资源不能被释放)导致服务器频繁且长时间FGC导致服务器CPU持续飚高 日志中内存溢出:java.lang.Ou ...

  2. 性能优化-CPU占用过高问题排查

    1. 性能优化是什么? 1.1 性能优化就是发挥机器本来的性能 1.2 性能瓶颈在哪里,木桶效应. CPU占用过高 1.现象重现 CPU占用过高一般情况是代码中出现了循环调用,最容易出现的情况有几种: ...

  3. svchost占用内存过高_是什么导致你的Java服务器内存和CPU占用过高呢

    一.内存占用过高 1.造成服务器内存占用过高只有两种情况:内存溢出或内存泄漏 (1)内存溢出:程序分配的内存超出物理内存的大小,导致无法继续分配物理内存,出现OOM报错. (2)内存泄漏:不再调用的对 ...

  4. java 内存很高_Java服务器内存和CPU占用过高的原因

    一.内存占用过高 1.造成服务器内存占用过高只有两种情况:内存溢出或内存泄漏 (1)内存溢出:程序分配的内存超出物理内存的大小,导致无法继续分配物理内存,出现OOM报错. (2)内存泄漏:不再调用的对 ...

  5. 线上java程序CPU占用过高问题排查

    简要 工作中负责的有一个项目是使用iReport+JasperReport实现的一个打印系统.最近这个线上程序经常无响应,重启后恢复正常,但是时不时还是会出现类似的问题. 最后发现是JasperRep ...

  6. CPU占用过高问题排查

    2019独角兽企业重金招聘Python工程师标准>>> 基本环境 tomcat 7 JDK 8 Linux 问题定位 查看后台异常 通过查看系统的后台日志,发现各个请求都正常,没有异 ...

  7. Java应用CPU占用过高问题排查

    文章目录 问题描述 问题分析 如果你的 Java 应用把 CPU 100% 打满,该怎么办呢? 下面就结合实际情况来说明,对于 Java 应用,CPU 消耗过高的时,该如何处理? CPU 消耗过高分析 ...

  8. linux poll cpu过高,CPU占用过高问题排查

    前几天发现测试环境的CPU一直很高,于是就去排查了一下原因,之前在程序管理里面介绍过,可以通过top命令查看linux系统进程的资源占用.于是运行top命令如下: top 从上图中可以看到其中有一个线 ...

  9. neo4j 查询同一节点的两个上级_如何用Neo4j和ScikitLearn做机器学习任务?| 附超详细分步教程...

    作者 | Mark Needham译者 | Tianyu.Shawnice编辑 | Jane出品 | AI科技大本营(ID:rgznai100)图算法不是一个新兴技术领域,在开源库中已经有很多功能强大 ...

最新文章

  1. 京东金融晒 “打黑成绩单”:一年内避免用户损失上亿元
  2. Ubuntu安装docker-ce,vagrant,virtualbox步骤
  3. php 循环curl,php中使用foreach curl多个URL及多线程请求多个URL
  4. #研发解决方案介绍#基于StatsD+Graphite的智能监控解决方案
  5. shell 学习笔记(四)
  6. C语言实现的FFT与IFFT源代码,不依赖特定平台
  7. 画王八java代码参数_java画乌龟源代码-郭遥航.doc
  8. 音频编码解码器库 libZPlay
  9. 古迪纳夫等3人获得诺贝尔化学奖 确立锂离子电池构成
  10. 在集设浏览学习高水准海报设计,会带给你不一样的灵感!
  11. Codeforces 319C DP 斜率优化
  12. inside MPQ
  13. 容器安装 libx264
  14. object与reflect
  15. xman_2019_format
  16. SQL注入-SQLmap-不同数据库注入
  17. Python非线性拟合自定义函数参数(对标MATLAB-nlinfit函数)
  18. python基础程序_Python基础初识
  19. 懒羊羊找朋友 C++
  20. 青龙面板关闭青龙二级验证

热门文章

  1. 视频分类/动作识别数据库研究现状
  2. 【Python】函数默认参数怎么改变?
  3. Python3打印当前系统时间
  4. 云炬随笔20211012(2)
  5. 怎么在linux上装java,如何在Ubuntu Linux上安装Java
  6. django 操作MySQL 中文乱码_Django 连接mysql数据库中文乱码
  7. OpenGL编程指南10:组合运动示例1—创建太阳系模型
  8. Qt修炼手册3_VS建立的Qt工程(或项目)生成pro文件
  9. 将数据从一个表剪切到另一个表中
  10. 认清JavaScript和JAVA全局变量和局部变量的作用域