当前位置: 首页 > news >正文

故障排查详解

故障排查详解

本章导读

系统故障不可避免,但快速定位和解决问题的能力决定了系统的可用性。本章系统讲解OOM、CPU飙升、死锁等常见故障的排查方法与工具使用,帮助读者建立完整的故障排查体系,从"盲人摸象"进化到"精准定位"。

学习目标

  • 目标1:掌握JDK诊断工具(jstack、jmap、jstat)的使用方法
  • 目标2:能够分析堆转储文件定位内存泄漏根因
  • 目标3:掌握CPU飙升问题的定位流程与常见原因分析
  • 目标4:能够检测和诊断线程死锁并制定预防策略
  • 目标5:建立系统化的故障排查思维框架与应急预案

前置知识:熟悉JVM内存模型与GC机制,了解多线程编程基础,具备Linux运维经验

阅读时长:约 50 分钟

一、知识概述

故障排查是保障系统稳定运行的核心能力。当系统出现异常时,能够快速定位问题根因并采取有效措施,是每个开发和运维人员必备的技能。本文将详细介绍Java应用常见故障的排查方法和工具使用。

1.1 故障排查体系

┌─────────────────────────────────────────────────────────────┐ │ 故障排查体系 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 故障发现 │ │ └── 监控告警、用户反馈、日志异常 │ │ │ │ 2. 故障定位 │ │ └── 分析症状、收集信息、定位原因 │ │ │ │ 3. 故障处理 │ │ └── 临时方案、根本解决、验证效果 │ │ │ │ 4. 故障复盘 │ │ └── 总结原因、改进措施、文档沉淀 │ │ │ │ 常见故障类型: │ │ ┌─────────────┬─────────────────────────────────────┐ │ │ │ OOM │ 内存溢出,应用崩溃 │ │ │ ├─────────────┼─────────────────────────────────────┤ │ │ │ CPU飙升 │ CPU占用过高,响应缓慢 │ │ │ ├─────────────┼─────────────────────────────────────┤ │ │ │ 死锁 │ 线程阻塞,功能不可用 │ │ │ ├─────────────┼─────────────────────────────────────┤ │ │ │ 响应慢 │ 接口超时,用户体验差 │ │ │ ├─────────────┼─────────────────────────────────────┤ │ │ │ 连接异常 │ 数据库/缓存连接失败 │ │ │ └─────────────┴─────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘

1.2 故障排查工具箱

┌─────────────────────────────────────────────────────────────┐ │ 故障排查工具箱 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ JDK工具 │ │ ├── jps - 查看Java进程 │ │ ├── jstat - JVM统计信息 │ │ ├── jinfo - 查看JVM配置 │ │ ├── jmap - 内存映射、堆转储 │ │ ├── jstack - 线程堆栈 │ │ ├── jcmd - 多功能诊断工具 │ │ └── jconsole - 图形化监控 │ │ │ │ 系统工具 │ │ ├── top/htop - 系统资源监控 │ │ ├── vmstat - 虚拟内存统计 │ │ ├── iostat - IO统计 │ │ ├── netstat - 网络连接 │ │ ├── lsof - 打开的文件 │ │ ├── strace - 系统调用跟踪 │ │ └── perf - 性能分析 │ │ │ │ 高级工具 │ │ ├── Arthas - 阿里开源诊断工具 │ │ ├── JProfiler - 商业性能分析工具 │ │ ├── MAT - 内存分析工具 │ │ └── async-profiler - 异步性能分析 │ │ │ └─────────────────────────────────────────────────────────────┘

二、OOM分析与排查

2.1 OOM类型与原因

┌─────────────────────────────────────────────────────────────┐ │ OOM类型与原因 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. Java heap space │ │ 原因:堆内存不足,对象过多无法回收 │ │ 解决:增大堆内存、分析内存泄漏、优化代码 │ │ │ │ 2. Metaspace / PermGen │ │ 原因:类加载过多、动态代理、反射使用过度 │ │ 解决:增大元空间、限制类加载、优化框架配置 │ │ │ │ 3. GC overhead limit exceeded │ │ 原因:GC时间过长,无法有效回收内存 │ │ 解决:优化GC参数、分析内存泄漏 │ │ │ │ 4. Direct buffer memory │ │ 原因:NIO直接内存不足 │ │ 解决:增大直接内存限制、检查NIO使用 │ │ │ │ 5. Out of swap space │ │ 原因:系统交换空间不足 │ │ 解决:增加系统内存、调整内存使用 │ │ │ │ 6. Requested array size exceeds VM limit │ │ 原因:请求的数组大小超过JVM限制 │ │ 解决:优化业务逻辑,避免创建超大数组 │ │ │ └─────────────────────────────────────────────────────────────┘

2.2 堆内存分析

# ============================================# 查看Java进程# ============================================jps-lvm# 输出示例:# 12345 myapp.jar -Xms2g -Xmx2g -XX:+UseG1GC# ============================================# 查看堆内存使用情况# ============================================jstat-gc1234510005# 输出说明:# S0C S1C S0U S1U EC EU OC OU MC MU# 512.0 512.0 0.0 128.0 8192.0 4096.0 16384.0 12288.0 8192.0 7168.0## S0C/S1C: Survivor区容量# S0U/S1U: Survivor区使用量# EC/EU: Eden区容量/使用量# OC/OU: 老年代容量/使用量# MC/MU: 元空间容量/使用量# ============================================# 生成堆转储文件# ============================================# 方式1: 使用jmapjmap-dump:format=b,file=heap.hprof12345# 方式2: 使用jcmdjcmd12345GC.heap_dump /tmp/heap.hprof# 方式3: 应用启动时自动生成(推荐生产环境)# -XX:+HeapDumpOnOutOfMemoryError# -XX:HeapDumpPath=/logs/heapdump.hprof# ============================================# 查看堆内存直方图# ============================================jmap-histo:live12345|head-30# 输出示例:# num #instances #bytes class name# ----------------------------------------------# 1: 50000 4000000 com.example.User# 2: 30000 2400000 java.lang.String# 3: 20000 1600000 java.util.HashMap$Node# ============================================# 使用MAT分析堆转储# ============================================# 1. 下载MAT: https://eclipse.dev/mat/# 2. 打开heap.hprof文件# 3. 查看Dominator Tree(支配树)# 4. 分析Leak Suspects(内存泄漏嫌疑)# 5. 查看Histogram(对象统计)

2.3 内存泄漏排查实战

// ============================================// 常见内存泄漏场景// ============================================// 场景1: 静态集合持有对象引用publicclassMemoryLeakDemo{// 静态集合会一直持有对象引用,导致无法被GCprivatestaticfinalMap<String,Object>CACHE=newHashMap<>();publicvoidaddToCache(Stringkey,Objectvalue){CACHE.put(key,value);// 如果不删除,会一直占用内存}// 正确做法:使用弱引用或定期清理privatestaticfinalMap<String,Object>WEAK_CACHE=newWeakHashMap<>();}// 场景2: 监听器未注销publicclassEventSource{privateList<EventListener>listeners=newArrayList<>();publicvoidaddListener(EventListenerlistener){listeners.add(listener);}// 忘记提供remove方法,导致监听器无法被回收// public void removeListener(EventListener listener) {// listeners.remove(listener);// }}// 场景3: ThreadLocal未清理publicclassThreadLocalLeak{privatestaticfinalThreadLocal<byte[]>THREAD_LOCAL=newThreadLocal<>();publicvoidprocess(){THREAD_LOCAL.set(newbyte[1024*1024]);// 1MB// 忘记清理// THREAD_LOCAL.remove();}}// 场景4: 数据库连接未关闭publicclassConnectionLeak{publicvoidquery(){Connectionconn=null;try{conn=dataSource.getConnection();// 执行查询}finally{// 忘记关闭连接// if (conn != null) conn.close();}}}// 场景5: 缓存无限增长publicclassCacheLeak{privateMap<String,CacheEntry>cache=newHashMap<>();publicvoidput(Stringkey,Objectvalue){cache.put(key,newCacheEntry(value,System.currentTimeMillis()));// 没有清理过期缓存的机制}// 正确做法:使用Caffeine等缓存框架// private Cache<String, Object> cache = Caffeine.newBuilder()// .maximumSize(10000)// .expireAfterWrite(Duration.ofMinutes(30))// .build();}
// ============================================// 内存泄漏排查示例// ============================================// 使用Arthas排查内存泄漏// 1. 启动Arthas// java -jar arthas-boot.jar// 2. 选择目标进程// 选择对应的Java进程编号// 3. 查看内存使用情况// dashboard// 4. 查看对象统计// heap
http://www.jsqmd.com/news/679097/

相关文章:

  • 魔兽争霸3优化完全指南:用WarcraftHelper解决现代系统兼容性问题
  • 2026届学术党必备的降重复率神器实测分析
  • 别再死记硬背了!用这5个方法搞定ADAS测试用例设计(附信号验证/诊断/升级实战案例)
  • 从混乱到有序:NSC_BUILDER 让你的 Switch 游戏库焕然一新
  • DROID-SLAM 夜晚超强(3) 数学模型 latex - MKT
  • golang如何使用expvar暴露运行时指标_golang expvar运行时指标暴露步骤
  • 【无标题】d wa dwa da w
  • 终极iOS设备降级工具:Legacy-iOS-Kit完全指南
  • Vitis自定义IP编译过了,Debug却卡在QEMU文件缺失?一个手动创建空文件的“土办法”救了我
  • 如何用MAA明日方舟助手彻底解放你的游戏时间?
  • 2026兰州复读学校排行:甘肃高三复读学校/甘肃高三文化课冲刺/甘肃高中复读学校/甘肃高考复读学校/甘肃高考文化课冲刺集训/选择指南 - 优质品牌商家
  • 爱奇艺发布纳逗Pro平台、新爱奇艺号和分账新规 今年预计上线3.5万部漫剧
  • 2026年4月西北机制净化板厂家排行:兰州中空玻镁岩棉净化板/兰州净化板厂家/兰州净化板生产厂家/兰州岩棉净化板/选择指南 - 优质品牌商家
  • 2026兰州钢塑波纹管技术全解析:兰州pe双壁波纹管/兰州pe聚乙烯波纹管/兰州pe钢带增强波纹管/兰州pe钢带增强螺旋波纹管/选择指南 - 优质品牌商家
  • 如何在Windows上快速安装苹果设备驱动程序:终极解决方案指南
  • 打印时隐藏元素_print样式display-none技巧【操作】
  • 保姆级教程:用dynv6免费域名+ddns-go,给你的Windows远程桌面挂个‘固定电话’
  • 3步完成微信聊天记录备份:WeChatExporter终极免费教程
  • Mac用户终极指南:如何用WeChatExporter轻松备份和恢复微信聊天记录
  • 面向高校机房还原卡替代的vDisk云桌面选型与建设参考
  • wa dda da w da w d
  • 5步轻松打造个人番茄小说图书馆:离线阅读的终极解决方案
  • AI大模型时代:9大高薪新岗位曝光,传统IT人如何转型抢占红利?
  • HTML怎么提升首屏加载_HTML关键资源内联策略【说明】
  • KH Coder:零代码文本挖掘神器,5分钟开启专业内容分析之旅
  • vDisk环境下机房保护卡更新操作指南
  • 部署本地AI大模型--ollma
  • (AI总结版)SQL Developer 安装好了,Oracle 21c XE 数据库已连接,之后的操作:搭建大数据开发的基础环境
  • 树莓派Pico与光电传感器打造实体解谜游戏控制器
  • Fedora 43 配置 ROCm 7.2 与 PyTorch 2.11