前言
本文章主要讲解内存分析、内存泄漏、内存溢出和CPU飙升的问题???
本文章使用Mac作为的开发工具
大纲
- 堆内存诊断工具
- 什么是内存泄漏、内存溢出
- 诊断死锁问题
- 诊断CPU飙升
- 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
- 3.2.2、选择线程检查死锁
四、诊断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飙升
- VisualVM找到该端口
- 查看飙升的线程
- 查看飙升线程的代码块
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
- 5.2.2. 生成dump文件
jmap -dump:live,format=b,file=x_admin.dump 1682
- 5.2.3. 打开jvisualvm
cd /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home/bin/jvisualvm
- 5.2.4. 装载dump到jvisualvm