[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f1b300lqgtfmoj":3,"$f250wz8h39yydc":8,"$f3e13fn86h0z0l":29,"$f1tmzc20p7l0cb":37,"$fs02kj72bvfsw":72,"toc--361680385-5-5":76},{"description":4,"domain":5,"id":6,"keywords":4,"title":7},"","api.kongjs.com",1,"默认",[9,20,24],{"children":10,"icon":4,"id":11,"linkType":12,"linkUrl":13,"parentId":14,"sort":15,"status":16,"target":17,"title":18,"visible":19},null,"447369447469600768","URL","\u002F","0",0,"1","_self","首页",true,{"children":10,"icon":4,"id":21,"linkType":12,"linkUrl":22,"parentId":14,"sort":15,"status":16,"target":17,"title":23,"visible":19},"447369693859794944","\u002Fnotes","笔记",{"children":10,"icon":4,"id":25,"linkType":26,"linkUrl":27,"parentId":14,"sort":15,"status":16,"target":17,"title":28,"visible":19},"447369977960976384","PAGE","\u002Fabout","关于我",{"category":30,"categoryId":31,"cover":10,"description":4,"fileId":10,"id":34,"publishAt":10,"tags":35,"title":36},{"articleCount":10,"children":10,"cover":10,"description":4,"fileId":10,"icon":4,"id":31,"parentId":14,"slug":32,"sort":15,"title":33},"453164732518506496","back-end","后端","453165633773772800",[],"Java面试核心知识",[38,41,44,48,52,56,60,64,68],{"children":10,"description":4,"id":39,"noteId":34,"parentId":14,"sort":15,"status":16,"title":40},"453165775620939776","Java基础核心全集（数据类型、拆箱装箱、克隆、对象结构、字符串、包装类、序列化）",{"children":10,"description":4,"id":42,"noteId":34,"parentId":14,"sort":6,"status":16,"title":43},"453166088570544128","JVM原理（JDK8~25）内存结构、分代模型、GC算法、垃圾收集器、元空间、双亲委派机制",{"children":10,"description":4,"id":45,"noteId":34,"parentId":14,"sort":46,"status":16,"title":47},"453166295265845248",2,"Java8至25 对象创建全过程及各版本底层演进差异",{"children":10,"description":4,"id":49,"noteId":34,"parentId":14,"sort":50,"status":16,"title":51},"453166545573519360",3,"Java集合全套原理（List+Map底层、扩容机制、线程安全集合对比）",{"children":10,"description":4,"id":53,"noteId":34,"parentId":14,"sort":54,"status":16,"title":55},"453166809651093504",4,"Java线程原理、六大状态流转、线程结束判断、安全中断、核心方法区别",{"children":10,"description":4,"id":57,"noteId":34,"parentId":14,"sort":58,"status":16,"title":59},"453167023724175360",5,"Java线程池原理、使用规范、常用并发异步工具类",{"children":10,"description":4,"id":61,"noteId":34,"parentId":14,"sort":62,"status":16,"title":63},"453167209447956480",6,"Java 虚拟线程与平台线程：原理、区别与实战使用",{"children":10,"description":4,"id":65,"noteId":34,"parentId":14,"sort":66,"status":16,"title":67},"453167452423987200",7,"CAS与AQS 底层原理、核心流程、面试最全详解",{"children":10,"description":4,"id":69,"noteId":34,"parentId":14,"sort":70,"status":16,"title":71},"453168570885480448",8,"线上服务器CPU飙升 Java代码 完整定位排查流程",{"content":73,"contentType":74,"description":4,"title":71,"wordCount":75},"# 线上服务器CPU飙升 Java代码 完整定位排查流程（生产实战\\+面试标准答案）\n\n线上CPU飙升是后端最高频故障，核心思路：**服务器定位高CPU进程 → 定位高CPU线程 → 打印线程栈 → 锁定问题代码 → 分析根因**。整套流程3分钟内可定位代码级问题。\n\n## 一、整体排查链路（口诀）\n\n**top 找进程 → top \\-H 找线程 → printf 转16进制 → jstack 抓栈 → 定位代码行**\n\n## 二、第一步：服务器层找到高CPU Java进程\n\n服务器执行：\n\n```shell\ntop\n```\n\n观察：CPU占用最高的 **PID**（一般是java进程）。\n\n假设高CPU进程PID = **12345**\n\n## 三、第二步：找到该进程下的【高CPU线程】\n\n进入进程线程视图：\n\n```shell\ntop -H -p 12345\n```\n\n\\-H：展示线程级别CPU占用\n\n找到占用CPU最高的 **线程TID**，例如：**67890**\n\n## 四、第三步：线程ID转16进制（jstack必备）\n\njstack 日志中线程ID是**16进制**，需要转换：\n\n```shell\nprintf \"%x\\n\" 67890\n```\n\n得到十六进制线程ID：**10812**\n\n## 五、第四步：jstack 打印堆栈，精准定位代码行\n\n```shell\njstack 12345 | grep -A 50 10812\n```\n\n\\-A 50：打印该线程后50行堆栈，直接看到**类名、方法、代码行号**\n\n此时可以直接锁定：**哪一行代码死循环、频繁计算、卡死**\n\n## 六、补充：全程一键排查命令（生产神器）\n\n线上可直接复制执行，自动抓取最高CPU线程堆栈：\n\n```shell\npid=$(top -bn1 | grep java | awk '{print $1}' | head -1)\ntid=$(top -Hbn1 -p $pid | awk '{print $1}' | head -2 | tail -1)\nhex_tid=$(printf \"%x\\n\" $tid)\njstack $pid | grep -A 100 $hex_tid\n```\n\n## 七、CPU飙升常见Java代码根因（99%场景）\n\n### 1\\. 死循环 \u002F 空循环（最常见）\n\nwhile\\(true\\)、for循环无退出条件、递归死递归\n\n现象：单个线程CPU 100%，线程栈固定卡在某行代码\n\n### 2\\. 复杂逻辑疯狂计算、大数据遍历\n\n超大List\u002FMap遍历、嵌套循环、笛卡尔积、复杂排序\n\n数据量小时没问题，线上数据量大直接CPU打满\n\n### 3\\. 正则表达式回溯卡死\n\n贪婪正则、复杂匹配导致 **正则回溯爆炸**，CPU飙升\n\n### 4\\. 频繁FullGC \u002F GC线程占满CPU\n\n不一定是业务代码！**GC线程CPU高**也是CPU飙高主力场景\n\n排查命令：\n\n```shell\njstat -gc 12345 1000\n```\n\n频繁 FGCT 上涨 → 内存溢出、内存泄漏、大对象创建\n\n此时需要配合 **jmap dump** 分析：\n\n```shell\njmap -dump:format=b,file=heap.hprof 12345\n```\n\n### 5\\. 锁自旋、CAS空转\n\n大量竞争锁、Unsafe CAS空转、synchronized 严重竞争导致线程自旋消耗CPU\n\n### 6\\. 定时任务频繁执行、死锁循环任务\n\nquartz、xxl\\-job 任务逻辑死循环、每秒高频执行\n\n## 八、如何区分：业务线程CPU高 VS GC线程CPU高\n\n- **业务线程高**：jstack 能看到业务代码堆栈 → 业务逻辑问题\n\n- **GC线程高**：jstack 看不到业务栈，GC任务爆满 → 内存问题（泄漏\u002F大对象\u002F频繁创建销毁）\n\n## 九、临时止血方案（线上紧急处理）\n\n1. 临时重启服务（快速恢复可用性）\n\n2. 临时关闭异常定时任务\n\n3. 限流、降级防止流量打垮服务\n\n4. dump 堆栈\\+内存文件，保留现场后重启\n\n## 十、面试极简背诵版（一句话流程）\n\n**线上CPU飙升，我先通过top找到高CPU进程PID，再用top \\-H定位高CPU线程TID，转16进制后通过jstack抓取该线程堆栈，直接定位到具体类和代码行；同时用jstat排查是否是GC导致的CPU飙高，区分业务死循环还是内存问题。**\n\n## 十一、拓展：日常预防手段\n\n- 线上开启线程池监控、GC监控、CPU告警\n\n- 禁止裸 while\\(true\\) 循环，增加休眠和退出条件\n\n- 大集合遍历、复杂计算做数据量限制\n\n- 定时任务错开高峰、控制执行频率","markdown",2028,{"frontmatter":77,"meta":78,"nodes":134},{},{"title":79,"description":80,"toc":81},"线上服务器CPU飙升 Java代码 完整定位排查流程（生产实战+面试标准答案）","线上CPU飙升是后端最高频故障，核心思路：服务器定位高CPU进程 → 定位高CPU线程 → 打印线程栈 → 锁定问题代码 → 分析根因。整套流程3分钟内可定位代码级问题。",{"title":4,"searchDepth":58,"depth":58,"links":82},[83,85,88,91,94,97,100,122,125,128,131],{"id":4,"depth":46,"text":84},"一、整体排查链路（口诀）",{"id":86,"depth":46,"text":87},"cpu-java-1","二、第一步：服务器层找到高CPU Java进程",{"id":89,"depth":46,"text":90},"cpu","三、第二步：找到该进程下的【高CPU线程】",{"id":92,"depth":46,"text":93},"id16jstack","四、第三步：线程ID转16进制（jstack必备）",{"id":95,"depth":46,"text":96},"jstack","五、第四步：jstack 打印堆栈，精准定位代码行",{"id":98,"depth":46,"text":99},"-1","六、补充：全程一键排查命令（生产神器）",{"id":101,"depth":46,"text":102,"children":103},"cpujava99","七、CPU飙升常见Java代码根因（99%场景）",[104,107,110,113,116,119],{"id":105,"depth":50,"text":106},"cpujava99-_1","1. 死循环 \u002F 空循环（最常见）",{"id":108,"depth":50,"text":109},"cpujava99-_2","2. 复杂逻辑疯狂计算、大数据遍历",{"id":111,"depth":50,"text":112},"cpujava99-_3","3. 正则表达式回溯卡死",{"id":114,"depth":50,"text":115},"cpujava99-_4-fullgc-gccpu","4. 频繁FullGC \u002F GC线程占满CPU",{"id":117,"depth":50,"text":118},"cpujava99-_5-cas","5. 锁自旋、CAS空转",{"id":120,"depth":50,"text":121},"cpujava99-_6","6. 定时任务频繁执行、死锁循环任务",{"id":123,"depth":46,"text":124},"cpu-vs-gccpu","八、如何区分：业务线程CPU高 VS GC线程CPU高",{"id":126,"depth":46,"text":127},"-2","九、临时止血方案（线上紧急处理）",{"id":129,"depth":46,"text":130},"-3","十、面试极简背诵版（一句话流程）",{"id":132,"depth":46,"text":133},"-4","十一、拓展：日常预防手段",[135,139,148,151,156,158,161,170,177,183,185,188,193,196,206,208,215,220,226,228,233,239,245,247,250,255,257,260,263,266,268,271,274,276,283,285,292,295,300,303,310,315,317,320,322,325,327,343,345,360,362,367,369],[136,137,79],"h1",{"id":138},"cpu-java",[140,141,142,143,147],"p",{},"线上CPU飙升是后端最高频故障，核心思路：",[144,145,146],"strong",{},"服务器定位高CPU进程 → 定位高CPU线程 → 打印线程栈 → 锁定问题代码 → 分析根因","。整套流程3分钟内可定位代码级问题。",[149,150,84],"h2",{"id":4},[140,152,153],{},[144,154,155],{},"top 找进程 → top -H 找线程 → printf 转16进制 → jstack 抓栈 → 定位代码行",[149,157,87],{"id":86},[140,159,160],{},"服务器执行：",[162,163,165],"pre",{"language":164},"shell",[166,167,169],"code",{"class":168},"language-shell","top",[140,171,172,173,176],{},"观察：CPU占用最高的 ",[144,174,175],{},"PID","（一般是java进程）。",[140,178,179,180],{},"假设高CPU进程PID = ",[144,181,182],{},"12345",[149,184,90],{"id":89},[140,186,187],{},"进入进程线程视图：",[162,189,190],{"language":164},[166,191,192],{"class":168},"top -H -p 12345",[140,194,195],{},"-H：展示线程级别CPU占用",[140,197,198,199,202,203],{},"找到占用CPU最高的 ",[144,200,201],{},"线程TID","，例如：",[144,204,205],{},"67890",[149,207,93],{"id":92},[140,209,210,211,214],{},"jstack 日志中线程ID是",[144,212,213],{},"16进制","，需要转换：",[162,216,217],{"language":164},[166,218,219],{"class":168},"printf \"%x\\n\" 67890",[140,221,222,223],{},"得到十六进制线程ID：",[144,224,225],{},"10812",[149,227,96],{"id":95},[162,229,230],{"language":164},[166,231,232],{"class":168},"jstack 12345 | grep -A 50 10812",[140,234,235,236],{},"-A 50：打印该线程后50行堆栈，直接看到",[144,237,238],{},"类名、方法、代码行号",[140,240,241,242],{},"此时可以直接锁定：",[144,243,244],{},"哪一行代码死循环、频繁计算、卡死",[149,246,99],{"id":98},[140,248,249],{},"线上可直接复制执行，自动抓取最高CPU线程堆栈：",[162,251,252],{"language":164},[166,253,254],{"class":168},"pid=$(top -bn1 | grep java | awk '{print $1}' | head -1)\ntid=$(top -Hbn1 -p $pid | awk '{print $1}' | head -2 | tail -1)\nhex_tid=$(printf \"%x\\n\" $tid)\njstack $pid | grep -A 100 $hex_tid",[149,256,102],{"id":101},[258,259,106],"h3",{"id":105},[140,261,262],{},"while(true)、for循环无退出条件、递归死递归",[140,264,265],{},"现象：单个线程CPU 100%，线程栈固定卡在某行代码",[258,267,109],{"id":108},[140,269,270],{},"超大List\u002FMap遍历、嵌套循环、笛卡尔积、复杂排序",[140,272,273],{},"数据量小时没问题，线上数据量大直接CPU打满",[258,275,112],{"id":111},[140,277,278,279,282],{},"贪婪正则、复杂匹配导致 ",[144,280,281],{},"正则回溯爆炸","，CPU飙升",[258,284,115],{"id":114},[140,286,287,288,291],{},"不一定是业务代码！",[144,289,290],{},"GC线程CPU高","也是CPU飙高主力场景",[140,293,294],{},"排查命令：",[162,296,297],{"language":164},[166,298,299],{"class":168},"jstat -gc 12345 1000",[140,301,302],{},"频繁 FGCT 上涨 → 内存溢出、内存泄漏、大对象创建",[140,304,305,306,309],{},"此时需要配合 ",[144,307,308],{},"jmap dump"," 分析：",[162,311,312],{"language":164},[166,313,314],{"class":168},"jmap -dump:format=b,file=heap.hprof 12345",[258,316,118],{"id":117},[140,318,319],{},"大量竞争锁、Unsafe CAS空转、synchronized 严重竞争导致线程自旋消耗CPU",[258,321,121],{"id":120},[140,323,324],{},"quartz、xxl-job 任务逻辑死循环、每秒高频执行",[149,326,124],{"id":123},[328,329,330,337],"ul",{},[331,332,333,336],"li",{},[144,334,335],{},"业务线程高","：jstack 能看到业务代码堆栈 → 业务逻辑问题",[331,338,339,342],{},[144,340,341],{},"GC线程高","：jstack 看不到业务栈，GC任务爆满 → 内存问题（泄漏\u002F大对象\u002F频繁创建销毁）",[149,344,127],{"id":126},[346,347,348,351,354,357],"ol",{},[331,349,350],{},"临时重启服务（快速恢复可用性）",[331,352,353],{},"临时关闭异常定时任务",[331,355,356],{},"限流、降级防止流量打垮服务",[331,358,359],{},"dump 堆栈+内存文件，保留现场后重启",[149,361,130],{"id":129},[140,363,364],{},[144,365,366],{},"线上CPU飙升，我先通过top找到高CPU进程PID，再用top -H定位高CPU线程TID，转16进制后通过jstack抓取该线程堆栈，直接定位到具体类和代码行；同时用jstat排查是否是GC导致的CPU飙高，区分业务死循环还是内存问题。",[149,368,133],{"id":132},[328,370,371,374,377,380],{},[331,372,373],{},"线上开启线程池监控、GC监控、CPU告警",[331,375,376],{},"禁止裸 while(true) 循环，增加休眠和退出条件",[331,378,379],{},"大集合遍历、复杂计算做数据量限制",[331,381,382],{},"定时任务错开高峰、控制执行频率"]