前言

本文章主要讲解内存分析、内存泄漏、内存溢出和CPU飙升的问题???
本文章使用Mac作为的开发工具

大纲

  1. 堆内存诊断工具
  2. 什么是内存泄漏、内存溢出
  3. 诊断死锁问题
  4. 诊断CPU飙升
  5. jvisualvm分析内存溢出问题

一、堆内存诊断工具

  • jps工具查看对内存占用情况
    jps
    jmap heap 进程id
  • Jconsole工具 图形化界面管理 线程、Cpu 堆内存
    目录:java8/jdk/bin/jconsole.exe

二、内存泄漏、内存溢出区别

  • 内存泄漏:申请内存后,堆内存一直不释放
  • 内存溢出:申请内存前,内存不足
  • 进程与进程通讯:使用RMI技术通讯

三、线程死锁诊断

3.1、产生背景

多线程中同步中嵌套同步

线程A 首先获得Object锁,再获取this锁
线程B 首先获取this锁,再获取Object锁

3.2、Jconsole诊断

  • 3.2.1、打开jconsole
    image.png
  • 3.2.2、选择线程检查死锁
    image.png

四、诊断CPU飙升

4.1、产生背景

  • 高并发时候,所有线程都在运行,消耗CPU资源
  • 定时任务(底层是死循环),定时任务与业务逻辑代码分开部署,有效解耦
  • 云服务器 Redis 根据6379端口注入挖矿程序(redis不允许外网访问)
  • 分布式锁 重试机制、死锁(当前节点如果没有抢到锁的时候【乐观锁】CAS自旋转)
    乐观锁:能够保证用户线程一直在用户态,缺点:消耗CPU资源
    自旋时候一定要设置次数,超出就抛异常回滚
  • 内存消耗过大,导致Full GC次数过多
  • 代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢
  • 线程由于某种原因而进入WAITING状态,该功能整体不可用,但是无法复现

4.2、如何避免

  • 对服务器接口做限流,熔断、降级
  • 接口耗时的代码不要写成同步,改用Mq异步处理
  • 定时项目和业务项目分开部署
    1、降低业务逻辑项目CPU消耗资源。2、更好实现定时分片执行
  • 云服务器不要随意开放端口号,结合nginx、lvs
  • 写自旋锁一定要控制死循环次数

4.2、如何排查

  • win查看任务管理器
  • Linux top命令
    系统监控软件:当服务器CPU飙升到一定阀值自动触发报警70%

4.3、java如何排查进程CPU飙升问题

  • 线程创建产生CPU飙升
    image.png
  • VisualVM找到该端口
    image.png
  • 查看飙升的线程
    image.png
  • 查看飙升线程的代码块
    image.png

4.3、核心排查步骤

1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。

2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。

3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.

4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了

5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。

6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;

五、jvisualvm分析内存溢出问题

5.1、Jvm实战参数性能调优

  • 查看垃圾回收清理垃圾的频率 jstat
  • 排查生产环境内存溢出问题
  • 使用jvisualvm监听生产环境虚拟机堆内存情况

5.2、jvisualvm监听生产环境虚拟机堆内存情况

  • 5.2.1. 查找ID
jps

image.png

  • 5.2.2. 生成dump文件
jmap -dump:live,format=b,file=x_admin.dump 1682

image.png

  • 5.2.3. 打开jvisualvm
cd /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/bin/jvisualvm
  • 5.2.4. 装载dump到jvisualvm
    image.png