故障诊断与线上排查

共 17 题
📑 题目列表 17 题
#
★★★

1. /actuator/caches 与缓存诊断

/actuator/caches 与缓存诊断是什么?

  • Actuator 缓存端点
  • 缓存指标与诊断
  • 缓存健康检查

/actuator/caches 是 Spring Boot Actuator 提供的缓存管理端点,用于查看应用中的所有缓存(Cache)及其配置(CacheManager、Cache 名称、缓存类型、TTL 等),并可执行缓存清除操作(DELETE 请求清空指定缓存)。它对缓存诊断的价值:其一,集中查看各缓存名称、底层实现(如 Caffeine、Redis、SimpleCache)与配置,排查缓存配置是否合理;其二,结合 /actuator/metrics 的缓存命中率、miss、缓存大小等指标,判断缓存是否命中率低、是否频繁失效;其三,通过清除缓存快速验证缓存数据是否陈旧或污染问题。配合缓存监控,可定位缓存导致的内存/性能问题。

Actuator 的 caches 端点提供"缓存管理 + 诊断"能力,配合 metrics 可评估缓存命中率与配置,通过清除操作验证缓存一致性。是 Spring 缓存排查的入口。

#
★★★

2. /actuator/configprops 与配置属性诊断

/actuator/configprops 与配置属性诊断是什么?

  • configprops 端点
  • 配置属性的查看
  • 配置诊断价值

/actuator/configprops 是 Spring Boot Actuator 端点,展示应用中被 @ConfigurationProperties 绑定的配置属性类及其实际值(包括默认值与用户覆盖值)。它对配置属性诊断的价值:其一,集中查看所有 @ConfigurationProperties 绑定的属性值,核对配置是否生效、是否被覆盖;其二,排查配置绑定错误(如类型不匹配、前缀错误、未生效的配置);其三,对比配置预期与实际生效值,定位"配置未生效"或"生效了但不符合预期"的问题。注意 configprops 可能暴露敏感信息,生产环境需通过 exposure 控制暴露。配合 Environment 查看与 /actuator/env,可完整诊断配置来源与覆盖链。

configprops 端点用于审计 @ConfigurationProperties 绑定的实际值,是定位"配置生效与覆盖"问题的手段。诊断时需注意保密与暴露控制。

#
★★★

3. /actuator/threaddump 与 /actuator/heapdump 的运维价值

/actuator/threaddump 与 /actuator/heapdump 的运维价值是什么?

  • threaddump 端点
  • heapdump 端点
  • 运维诊断价值

/actuator/threaddump 返回当前所有线程的栈快照(线程状态、堆栈、锁信息),用于诊断线程卡死、死锁、资源竞争、CPU 高时的线程热点;/actuator/heapdump 生成 JVM 堆 dump(hprof 文件),用于分析内存占用、对象分布、内存泄漏与堆溢出。运维价值:threaddump 可快速定位"线程卡在哪个方法/锁"(配合多次取样对比),heapdump 可深入分析"堆被什么占用、是否存在泄漏"。两者是 Spring Boot 应用线上诊断的"线程 + 内存"两大抓手,配合 GC 日志与监控,可高效定位性能与内存问题。

两者是"线程视角 + 堆视角"的运维诊断入口:threaddump 看线程状态与卡点,heapdump 看对象与泄漏。对比多次取样可区分瞬时问题与持续问题。

#
★★★

4. /proc/sys/kernel/core_pattern 与 JVM core dump

/proc/sys/kernel/core_pattern 与 JVM core dump 的关系是什么?

  • core_pattern 的作用
  • JVM core dump
  • 崩溃诊断

/proc/sys/kernel/core_pattern 是 Linux 内核用于指定 core dump(core 文件)生成方式的参数,定义进程崩溃时 core 文件的位置与命名规则(如 %p 进程号、%e 可执行文件名),也支持把 core 通过管道交给外部程序(如系统级收集器)。JVM 崩溃(如本地方法错误、JVM 内部致命错误)时可能生成 core dump,包含进程内存、寄存器、线程栈等完整状态,用于离线分析崩溃根因。诊断价值:配置 core_pattern 让崩溃时可靠生成 core 文件,配合 gdb 分析 core 可定位 JVM 崩溃发生点(如 JNI 代码、编译器 bug)。若 core_pattern 被禁用或指向 /dev/null,则无法获得 core 文件,应调整配置以支持崩溃诊断。

core_pattern 决定"崩溃时 core 是否生成、生成到哪里"。JVM 崩溃排查依赖 core 文件,因此正确配置 core_pattern(含命名与去重)是崩溃诊断的基础。

#
★★★

5. OutOfMemoryError 后保留堆 dump 的 JVM 参数

OutOfMemoryError 后保留堆 dump 的 JVM 参数是什么?

  • HeapDumpOnOutOfMemoryError
  • HeapDumpPath
  • 自动保留堆 dump

在 OOM 时自动保留堆 dump 的关键参数是 -XX:+HeapDumpOnOutOfMemoryError,当 JVM 抛出 OutOfMemoryError 时自动生成堆 dump 文件;-XX:HeapDumpPath=路径 指定 dump 文件位置(默认在进程工作目录)。配合 -XX:+ExitOnOutOfMemoryError 或 -XX:+CrashOnOutOfMemoryError 可控制 OOM 后行为(退出或崩溃以便保留现场)。这些参数的核心价值是"在 OOM 发生瞬间自动保留现场",避免事后难以复现。dump 文件可用 MAT 分析泄漏根因。生产环境建议开启 HeapDumpOnOutOfMemoryError 并指定 HeapDumpPath,同时确保磁盘空间足够。

自动保留堆 dump 是 OOM 排查的第一步——在崩溃瞬间抓取现场。HeapDumpOnOutOfMemoryError + HeapDumpPath 是标准配置,配合 MAT 分析可定位泄漏。

// OOM 时自动保留堆 dump
// -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dumps/heap_%pid.hprof
// 可选:OOM 后退出释放现场
// -XX:+ExitOnOutOfMemoryError
#
★★★

6. Safepoint 偏差(Safepoint Bias)诊断

Safepoint 偏差(Safepoint Bias)是什么,如何诊断?

  • Safepoint Bias 的概念
  • 成因与影响
  • 诊断方法

Safepoint 偏差(Safepoint Bias)指某线程长时间停留在安全点区域(Safepoint 前后),导致其他线程到达 Safepoint 后迟迟无法进入,停摆(stop)被拉长,从而造成 GC 停顿显著拉长。成因:线程长时间运行不进入轮询点(如长时间 native 调用、CPU 密集计算、内存映射),或长期持有资源导致其他线程等待。诊断:用 -XX:+PrintSafepointStatistics 或 -XX:+SafepointTimeout 输出 Safepoint 统计与每次停顿的线程;用 JFR 的 jdk.Safepoint 事件记录停顿;对比多次 GC 日志的停顿时间与 Safepoint 事件,定位是"哪个线程在 Safepoint 拖慢"。修复:优化长时间 native 调用、减少持锁时间、排查热点代码。

Safepoint Bias 的本质是"单个线程拖慢全局 Safepoint 停顿"。诊断靠 PrintSafepointStatistics / JFR Safepoint 事件定位拖延线程,修复靠优化线程行为。

// 输出 Safepoint 统计
// -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1
// JFR 采集 Safepoint 事件
// jcmd <pid> JFR.start settings=profile
#
★★

7. CPU 飙高时 top -H 定位线程 + jstack 分析栈的完整流程

CPU 飙高时用 top -H 定位线程 + jstack 分析栈的完整流程是什么?

  • top -H 定位线程
  • 线程号转十六进制
  • jstack 分析栈

CPU 飙高时定位线程的完整流程:先用 top 查看整体 CPU,确认是哪个进程;再用 top -H -p 查看该进程内各线程的 CPU 占用,找到 CPU 最高的线程(记下其 PID/线程号);把线程号转十六进制(printf '%x' 线程号);用 jstack 抓取线程栈,在 dump 中搜索该十六进制线程号,定位到线程对应的栈,分析是业务热点、GC 线程、还是阻塞/死锁。从栈中可看到方法调用链,判断 CPU 高是业务计算、GC、还是锁竞争。必要时结合 jstat 看 GC 是否高频。

流程是"top 找进程 → top -H 找线程 → 转十六进制 → jstack 找栈 → 分析根因"。线程号转十六进制是连接 top 与 jstack 的关键。

// top 找进程
// top -p <pid>
// 线程级 CPU
// top -H -p <pid>
// 线程号转十六进制
// printf '%x\n' <thread_id>
// 抓栈
// jstack <pid> > thread_dump.txt
#
★★

8. jcmd GC.heap_dump 的堆 dump 与 MAT 分析

jcmd GC.heap_dump 的堆 dump 与 MAT 分析是如何做的?

  • jcmd GC.heap_dump 用法
  • 堆 dump 生成
  • MAT 分析

jcmd GC.heap_dump 用于生成指定进程的堆 dump(hprof 文件),是 jmap 的替代、更现代且不依赖模式。生成的 dump 用 MAT(Memory Analyzer)分析:打开 dump 后,MAT 给出 Leak Suspects(泄漏嫌疑)、Dominator Tree(支配树,显示对象占用)、Histogram(对象直方图)、OQL(对象查询)。重点看 Retained Heap(保留大小,即对象被回收后释放的空间)排序,找大对象与泄漏根;用"Path to GC Roots"(到达 GC Roots 的路径)查看对象如何被引用,定位是谁持有的泄漏引用。这样可定位泄漏来源并给出修复建议。

jcmd GC.heap_dump 负责抓取,MAT 负责分析(支配树、GC Roots 路径、直方图)。"Retained Heap + 到 GC Roots 的路径"是定位泄漏的核心。

// 生成堆 dump
// jcmd <pid> GC.heap_dump /data/heap_$(date +%s).hprof
// 用 MAT 打开 hprof,分析 Leak Suspects / Dominator Tree / Path to GC Roots
#
★★

9. jstack 线程 dump 的分析方法(死锁、阻塞、热点)

jstack 线程 dump 的分析方法(死锁、阻塞、热点)是什么?

  • 死锁检测
  • 阻塞分析
  • 热点定位

jstack 生成线程 dump 后,分析要点:死锁——dump 中会明确标注 "Found one Java-level deadlock" 及参与线程与锁,可直接定位;阻塞——看线程状态(BLOCKED/WAITING/TIMED_WAITING)与 "waiting to lock" / "parking to wait" 信息,判断是锁竞争还是等待资源;热点——结合 CPU 高(top -H + 十六进制匹配)定位 CPU 消耗最高的线程栈。多次取样(间隔数秒抓多个 dump)可区分"持续阻塞"与"瞬时热点",并观察线程是否长期卡在某个锁/方法。分析时关注线程栈顶、锁信息与调用链。

jstack 分析是三块:死锁自动标注、阻塞看状态与锁、热点配 CPU 匹配。多次取样对比是区分问题的关键手法。

#
★★

10. 堆外内存泄漏(NMT/直接内存/Netty)排查路径,Native Memory Tracking 的启用与 diff 分析

堆外内存泄漏(NMT/直接内存/Netty)排查路径是什么?Native Memory Tracking 如何启用与 diff 分析?

  • NMT 的启用
  • 堆外内存分类
  • diff 分析

堆外内存泄漏排查以 NMT(Native Memory Tracking)为核心。启用:-XX:NativeMemoryTracking=summary(或 detail),默认只记录,需先用 jcmd VM.native_memory baseline 建立基线,运行一段时间后 jcmd VM.native_memory summary.diff 对比增量,找出增长最快的类别(如 Internal、Arena、Class、Direct buffer 等)。直接内存/Netty 泄漏:Netty 的 DirectBuffer 占用堆外,可通过 NMT 的 "Internal" 或反射统计 Bits.totalCapacity 观察,配合 Netty 泄漏检测(-Dio.netty.leakDetection.level=paranoid)定位未 release 的 ByteBuf。排查路径:启用 NMT → baseline → 观察 diff → 定位增长类别 → 结合代码/框架(Netty、RocketMQ 等)定位未释放的堆外分配 → 修复并验证。

NMT 是堆外内存的"监控账本",diff 分析定位"哪些类别在增长"。结合 Netty 泄漏检测,可定位 DirectBuffer 等堆外泄漏的具体来源。

// 启用 NMT(summary 或 detail)
// -XX:NativeMemoryTracking=summary
// 建立基线与对比
// jcmd <pid> VM.native_memory baseline
// jcmd <pid> VM.native_memory summary.diff
// Netty 泄漏检测
// -Dio.netty.leakDetection.level=paranoid
#
★★

11. JVM 故障排查工具链(jps/jstack/jmap/jstat/jcmd/jhat/jfr)

JVM 故障排查工具链(jps/jstack/jmap/jstat/jcmd/jhat/jfr)各有什么作用?

  • 各工具的功能
  • 工具组合
  • 适用场景

JVM 故障排查工具链:jps(列出 JVM 进程)、jstack(线程 dump,看线程状态/锁)、jmap(堆信息、堆 dump、class histogram)、jstat(GC 与内存统计)、jcmd(多功能诊断命令,如 GC.heap_dump、VM.flags、Thread.print)、jhat(分析堆 dump 的 HTML 工具,已过时,多用 MAT 替代)、jfr(Flight Recorder 采集运行期剖析数据)。组合使用:定位进程用 jps,CPU 高用 jstack + top,内存/GC 用 jstat + jcmd + jmap,深度剖析用 jfr。不同工具对应不同排查维度,按需组合。

工具链覆盖"进程/线程/GC/内存/剖析"各维度。jcmd 是现代化多功能入口,jfr 是深度剖析利器,jhat 已被 MAT 取代。选对工具组合能高效定位问题。

#
★★

12. jcmd VM.command_line 与启动参数核查

jcmd VM.command_line 与启动参数核查是什么?

  • VM.command_line 命令
  • 启动参数核查
  • 诊断价值

jcmd VM.command_line 用于查看指定 JVM 进程的完整启动命令行参数(包括 java 命令、JVM 参数、classpath、主类等),用于核查实际启动参数是否符合预期。诊断价值:确认线上进程是否带上了预期的 -Xmx、-XX:UseG1GC、GC 日志等参数;排查"参数未生效"(如配置了 g1 但进程实际用默认);对比不同环境参数差异;核对 flags 是否被 Ergonomics 覆盖。配合 VM.flags(查看最终生效的 flag 值)与 VM.system_properties,可完整核查进程的启动与实际运行配置。

VM.command_line 看"启动时传了什么",是核查配置是否正确落地的第一手证据。结合 VM.flags 看"最终生效值",可定位参数未生效/被覆盖问题。

// 查看启动命令行
// jcmd <pid> VM.command_line
// 查看最终生效的 flag
// jcmd <pid> VM.flags -all
#
★★

13. jcmd VM.flags 与 VM.system_properties

jcmd VM.flags 与 VM.system_properties 的作用是什么?

  • VM.flags 命令
  • VM.system_properties
  • 配置核查

jcmd VM.flags 用于查看指定 JVM 进程的最终生效的 JVM 标志(flag)值,包括命令行显式设置与默认值,可说明哪些参数命令已生效、哪些被 Ergonomics 调整;jcmd VM.system_properties 用于查看 JVM 的系统属性(System.getProperties()),包括系统属性、环境相关配置、用户传递的 -D 属性等。两者的诊断价值:VM.flags 核查 JVM 参数是否按预期生效(如确认 UseG1GC、Xmx 等),VM.system_properties 核查应用相关系统属性(如编码、网络、框架配置)是否设置正确。配合 VM.command_line 与前两者,可完整复盘进程的配置状态。

VM.flags 看"JVM 参数最终值",VM.system_properties 看"系统属性",两者是核查配置生效状态的两类视图。可用于定位"参数没生效"或"属性被改"问题。

#
★★

14. jmap -heap 与 jmap -histo 的内存分析

jmap -heap 与 jmap -histo 的内存分析是什么?

  • jmap -heap
  • jmap -histo
  • 内存分析

jmap -heap 输出 JVM 堆的配置与使用情况(堆大小、各代(新生代/老年代)的容量与使用量、GC 统计、收集器信息),用于快速查看堆结构与内存占用;jmap -histo 输出堆中对象的类直方图(每个类的实例数与其占用空间,按占用排序),用于快速定位"哪类对象占用了大量内存"。两者是快速内存分析手段,无需抓完整 dump:-heap 看堆整体结构与池,-histo 看对象分布与可疑大对象/泄漏嫌疑类。注意 jmap 在特定场景可能触发 GC 或影响性能,生产慎用;详细分析仍需堆 dump + MAT。

jmap -heap 看"堆配置与使用",jmap -histo 看"对象直方图",是快速定位内存占用点的轻量手段;重分析用 dump + MAT。两者互补。

// 查看堆配置与使用
// jmap -heap <pid>
// 查看对象直方图(按占用排序)
// jmap -histo <pid>
#

15. Arthas 在线诊断常用命令(watch/trace/tt/stack)的方法入参与返回值捕获

Arthas 在线诊断常用命令(watch/trace/tt/stack)如何捕获方法入参与返回值?

  • watch 命令
  • trace/tt/stack
  • 入参与返回值捕获

Arthas 在线诊断常用命令:watch 监听方法调用,可观察方法入参、返回值、异常,并支持条件过滤(如 -x 展开深度、params[0] 等);trace 追踪方法调用路径,统计方法内部子调用的耗时,定位性能瓶颈;tt(TimeTunnel)记录方法调用快照,可回放某次调用的入参、返回值与异常,便于事后分析;stack 输出方法被调用的完整调用栈,定位调用来源。捕获入参与返回值:watch 用 params(入参)、returnObj(返回值)、throwExp(异常),配合 -x 展开对象字段;tt 用 -i 指定调用序号 view 查看入参/返回值。这些命令无需改代码即可在线诊断,适合排查线上问题。

watch 看入参/返回值/异常,trace 看调用耗时,tt 回放调用快照,stack 看调用栈。四者配合可在不重启的情况下在线诊断线上接口问题。

// watch 查看入参与返回值
// watch com.example.OrderService placeOrder params returnObj -x 3
// tt 记录并回放调用
// tt -t com.example.OrderService placeOrder
// tt -i 1000
// trace 查看调用耗时
// trace com.example.OrderService placeOrder
#

16. Arthas 的 ognl 表达式在动态修改方法参数与热更新中的应用边界

Arthas 的 ognl 表达式在动态修改方法参数与热更新中的应用边界是什么?

  • ognl 表达式
  • 动态修改参数
  • 热更新边界

Arthas 的 ognl 命令用 OGNL 表达式在运行时访问/修改对象属性、调用方法、查看静态字段,实现"动态修改方法参数"(如临时改某个对象的字段、调用方法、修改配置)和热更新(结合 redefine 或热重载类)。但应用边界有限:其一,ognl 修改的是"运行时对象状态",无法改变已编译方法的字节码逻辑本身(除非配合 redefine/热插桩);其二,ognl 表达式受 JVM 安全限制(模块化、私有字段访问受限,需前向设置);其三,动态修改只影响当前进程、重启即失,且易引入不一致,应在测试/灰度环境使用;其四,热更新(redefine)对类的方法体/注解等有限制,不能增删方法字段。因此 ognl 适合"临时诊断与纠错",而非生产长期手段。

ognl 是"运行时对象级操作",能改状态与方法参数,但改不了字节码逻辑(需 redefine)。其边界是"临时、进程内、有安全与结构限制",生产应谨慎。

#

17. JDK 26 故障诊断工具的演进全景

JDK 26 故障诊断工具的演进全景是什么?

  • JDK 26 诊断工具演进
  • 新能力
  • 与既有工具的整合

JDK 26 的故障诊断工具演进总体方向是"更统一、更安全、更易用"。具体包括:JFR(Flight Recorder)持续增强(更多事件、更低开销、更完善的事件分类);jcmd 作为统一诊断入口不断扩展(新增/增强子命令);持续改进 GC 日志(-Xlog)与堆分析流程;JEP 相关(如 Class-File API 的成熟)为字节码分析提供官方能力;以及统一的诊断 API(JFR 编程接口、Diagnostic Command)与监控(如 JFR 事件流、故障诊断命令的标准化)。演进全景体现为"从碎片化命令走向统一的事件流 + 命令 + 日志",让故障诊断更可观测、可自动化、跨工具一致。

JDK 26 诊断工具演进是"统一化 + 可观测化":JFR 事件流、jcmd 统一命令、统一日志、官方字节码 API 共同构成现代诊断体系,减少碎片化,提升排查效率。