Linux jstack 与 jmap 命令安装与实战指南本文是云悦智销项目后端运维技术栈的一部分。在部署 Java 项目后jstack 和 jmap 是排查线上问题的必备工具。本文系统讲解如何在 Linux 服务器上安装这两个命令以及基本的排查使用方法。目录jstack 与 jmap 简介安装准备安装 JDK 开发版获取 jstack 和 jmap验证安装jstack 命令实战jmap 命令实战常见问题排查项目中的应用场景一、jstack 与 jmap 简介1.1 两个命令的作用┌──────────┬──────────────────────────────────────────────────────────┐ │ 命令 │ 作用 │ ├──────────┼──────────────────────────────────────────────────────────┤ │ jstack │ Java Stack Trace — 查看 Java 进程的线程堆栈信息 │ │ │ │ │ │ 应用场景 │ │ │ • 线程死锁Deadlock │ │ │ • 线程阻塞Blocked │ │ │ • 线程大量 WAITING等待锁 │ │ │ • CPU 占用高的线程定位 │ │ │ • 线程池状态分析 │ │ │ │ │ │ 输出线程状态、调用栈、等待的锁、持有的锁 │ ├──────────┼──────────────────────────────────────────────────────────┤ │ jmap │ Java Memory Map — 查看 Java 进程的堆内存分布 │ │ │ │ │ │ 应用场景 │ │ │ • 内存泄漏排查 │ │ │ • 对象数量统计 │ │ │ • 生成堆转储文件heap dump用于 MAT/VisualVM 分析 │ │ │ • 查看堆内存使用率 │ │ │ │ │ │ 输出对象数量、内存分布、堆转储文件 │ └──────────┴──────────────────────────────────────────────────────────┘ 一句话 jstack → 看线程CPU 高、卡顿、死锁 jmap → 看内存内存溢出、内存泄漏1.2 命令对比┌──────────────┬─────────────────────────┬─────────────────────────┐ │ 维度 │ jstack │ jmap │ ├──────────────┼─────────────────────────┼─────────────────────────┤ │ 关注点 │ 线程状态 │ 内存分配 │ │ 触发场景 │ CPU100%、线程卡顿 │ OOM、内存持续增长 │ │ 输出文件 │ 文本日志 │ 二进制.hprof 文件 │ │ 影响性能 │ 几乎无影响 │ 生成 dump 时有短暂停顿 │ │ 常用参数 │-l-m-f│-heap-histo-dump│ └──────────────┴─────────────────────────┴─────────────────────────┘二、安装准备2.1 为什么需要安装问题 Linux 服务器上默认只安装了 JREJava Runtime Environment JRE 不包含 jstack、jmap 等诊断工具 解决 需要安装 JDKJava Development Kit的 devel 版本 开发版运行时 诊断工具 开发工具2.2 检查系统环境# 1. 查看 Linux 发行版cat/etc/os-release# 或lsb_release-a# 2. 查看当前 Java 版本java-version# 3. 查看已安装的 Java 包rpm-qa|grepjava# 4. 查看 jstack/jmap 是否已存在jstack--help# 如果提示 command not found说明未安装jmap-h# 同上2.3 系统环境信息┌────────────┬────────────────────────────────────────┐ │ 操作系统 │ CentOS7/8、RHEL、Ubuntu │ │ Java 版本 │ JDK1.8/11/17│ │ 包管理器 │ yumCentOS/RHEL │ │ │ apt-getUbuntu/Debian │ └────────────┴────────────────────────────────────────┘三、安装 JDK 开发版获取 jstack 和 jmap3.1 CentOS/RHEL 方式yum# 步骤 1切换到 root 用户suroot# 步骤 2查看可用的 Java 版本yum list--showduplicate|grepjava# 或更精确的搜索yum list--showduplicate|grep-ijava.*jdk# 步骤 3安装对应版本的 JDK 开发版# 以 JDK 11 为例yuminstalljava-11-openjdk-devel.x86_64-y# 如果是 JDK 1.8yuminstalljava-1.8.0-openjdk-devel.x86_64-y# 如果是 JDK 17yuminstalljava-17-openjdk-devel.x86_64-y3.2 Ubuntu/Debian 方式apt-get# 步骤 1更新包列表sudoapt-getupdate# 步骤 2查看可用的 Java 版本apt-cachesearch openjdk# 步骤 3安装 JDK 开发版# JDK 11sudoapt-getinstallopenjdk-11-jdk-y# JDK 1.8sudoapt-getinstallopenjdk-8-jdk-y# JDK 17sudoapt-getinstallopenjdk-17-jdk-y3.3 安装命令流程图安装流程 yum list--showduplicate→ 查看所有可用版本 │ ├──grep-ijava*→ 过滤 Java 相关包 │ └── 找到对应版本 → 如 java-11-openjdk-devel.x86_64 │ yuminstalljava-11-openjdk-devel.x86_64-y│ └── 安装完成3.4 各版本对比┌────────────────────────┬──────────┬──────────┬──────────┐ │ 包名 │ JDK 版本 │ 支持年份 │ 推荐度 │ ├────────────────────────┼──────────┼──────────┼──────────┤ │ java-1.8.0-openjdk │ JDK8│2014│ ⭐⭐⭐⭐ │ │ java-11-openjdk │ JDK11│2018│ ⭐⭐⭐⭐⭐ │ │ java-17-openjdk │ JDK17│2021│ ⭐⭐⭐⭐ │ └────────────────────────┴──────────┴──────────┴──────────┘ 云悦智销项目推荐使用 JDK11企业级长期支持版本四、验证安装4.1 检查 jstack# 方法 1查看帮助信息jstack--help# 方法 2查看版本jstack-version# 成功标志显示帮助信息或版本号# 失败标志command not found4.2 检查 jmap# 方法 1查看帮助信息jmap-h# 方法 2查看版本jmap-version# 成功标志显示帮助信息或版本号# 失败标志command not found4.3 完整验证脚本#!/bin/bash# verify_jdk.sh - 验证 JDK 安装echo JDK 安装验证 # 1. 检查 javaecho1. Java 版本java-versionecho# 2. 检查 javac需要开发版才有的编译器echo2. javac 版本javac-versionecho# 3. 检查 jstackecho3. jstack 命令jstack--help21|head-3||echojstack 未安装echo# 4. 检查 jmapecho4. jmap 命令jmap-h21|head-3||echojmap 未安装echo# 5. 检查 JAVA_HOMEecho5. JAVA_HOMEecho$JAVA_HOMEechoecho 验证完成 五、jstack 命令实战5.1 基本用法# 语法jstack[options]pid# 常用选项# -l 打印锁的额外信息锁状态、等待队列# -m 打印 Java 和本地C/C帧的混合栈# -f 输出所有线程的栈追踪# -h 打印帮助信息5.2 实战 1查看线程状态# 步骤 1查找 Java 进程 PIDjps-l# 列出所有 Java 进程ps-ef|grepjava# 或用 ps 命令# 步骤 2使用 jstack 查看线程堆栈jstackpid# 基本查看jstack-lpid# 带锁信息查看jstack-mpid# 含本地帧# 输出示例pool-1-thread-1#15 prio5 os_prio0 tid0x00007f...java.lang.Thread.State: RUNNABLE at com.example.OrderService.queryOrder(OrderService.java:50)at com.example.OrderController.list(OrderController.java:30)...5.3 实战 2排查死锁# 查看死锁jstack 会自动检测jstack-lpid|grep-A5Deadlock# 如果存在死锁输出类似Thread-A#10 daemon prio5 os_prio0 tid0x00007f...java.lang.Thread.State: BLOCKED(on object monitor)at com.example.LockTest.methodA(LockTest.java:20)- waiting to lock0x00000006c0e00d80(a java.lang.Object)Thread-B#11 daemon prio5 os_prio0 tid0x00007f...java.lang.Thread.State: BLOCKED(on object monitor)at com.example.LockTest.methodB(LockTest.java:35)- waiting to lock0x00000006c0e00e00(a java.lang.Object)Found one Java-level deadlock:Thread-A:waiting to lock monitor 0x00007f...(object 0x00000006c0e00e00)whichis held byThread-BThread-B:waiting to lock monitor 0x00007f...(object 0x00000006c0e00d80)whichis held byThread-A5.4 实战 3排查 CPU 高# 步骤 1找到 CPU 占用高的进程top-H-ppid# 查看该进程下所有线程的 CPU 占用# 步骤 2找到 CPU 最高的线程 PID十进制# 假设线程 ID 为 12345# 步骤 3转换为十六进制printf%x\n12345# 输出3039# 步骤 4在 jstack 输出中搜索该十六进制线程 IDjstackpid|grep-A203039# 输出示例pool-1-thread-1#15 prio5 os_prio0 tid0x00007f...java.lang.Thread.State: RUNNABLE at com.example.OrderService.queryOrder(OrderService.java:50)at com.example.OrderController.list(OrderController.java:30)5.5 线程状态速查┌────────────────┬────────────────────────────────────────────┐ │ 线程状态 │ 含义 │ ├────────────────┼────────────────────────────────────────────┤ │ RUNNABLE │ 正在运行或等待 CPU 调度 │ │ BLOCKED │ 等待获取监视器锁synchronized 锁 │ │ WAITING │ 无限期等待其他线程执行如 Object.wait() │ │ TIMED_WAITING │ 有限期等待如 Thread.sleep(time) │ │ NEW │ 线程刚创建尚未 start()│ │ TERMINATED │ 线程已执行完成 │ └────────────────┴────────────────────────────────────────────┘ 常见异常 • 大量 BLOCKED → 锁竞争严重考虑优化锁粒度 • 大量 WAITING → 线程池可能等待任务正常 • 大量 TIMED_WAITING → 线程在sleep或等待超时 • RUNNABLE 长时间不释放 → 可能有死循环或复杂计算5.6 jstack 常用命令汇总# 查看指定进程的线程状态jstack12345# 查看线程堆栈并保存文件jstack12345thread_dump.txt# 查看带锁信息的线程状态jstack-l12345# 持续监控每 1 秒输出一次共 10 次foriin{1..10};dojstack12345sleep1donethread_monitor.log# 查看 Java 本地栈jstack-m12345六、jmap 命令实战6.1 基本用法# 语法jmap[options]pid# 常用选项# -heap 打印堆内存配置和使用情况# -histo[:live] 打印堆中对象统计:live 只统计存活对象# -dump:formatb,filefile 生成堆转储文件# -finalizerinfo 打印等待回收的对象6.2 实战 1查看堆内存使用# 查看堆内存配置和使用情况jmap-heappid# 输出示例Heap Configuration: MinHeapFreeRatio40MaxHeapFreeRatio70MaxHeapSize2147483648(2048.0MB)NewSize713031680(680.0MB)OldSize1434451968(1368.0MB)Heap Usage: NEW generation(Eden 1Survivor): Eden Space: capacity671088640(640.0MB)used438536192(418.17MB)free232552448(221.83MB)65.34905916213989% used OLD generation: capacity1434451968(1368.0MB)used1234567890(1177.26MB)free199884078(190.74MB)86.06494242983903% used6.3 实战 2查看对象统计# 查看堆中各类对象的数量和大小jmap-histopid# 只看存活对象jmap-histo:livepid# 输出示例# Class Objects Size ByteCode1: byte[]1234569876549876542: java.lang.String56789123456712345673: com.example.Order2345623456782345678...6.4 实战 3生成堆转储# 生成堆转储文件用于后续分析jmap-dump:formatb,fileheapdump.hprofpid# 只 dump 存活对象jmap -dump:live,formatb,fileheapdump.hprofpid# 说明# • heapdump.hprof 文件可能很大几百 MB 到几个 GB# • 生成时 JVM 会暂停几秒到几十秒STW# • 用 MAT (Memory Analyzer Tool) 或 VisualVM 打开分析6.5 内存问题分析流程内存问题排查流程 JVM 内存持续增长 │ jmap-heappid← 查看堆内存使用率 │ 如果 Old 区使用率80% │ jmap-histo:livepid← 查看哪类对象最多 │ 如果发现某对象数量异常 │ jmap -dump:live,formatb,fileheapdump.hprofpid│ 下载 hprof 文件 → MAT / VisualVM 分析 │ 找到内存泄漏原因七、常见问题排查7.1 jstack/jmap 命令找不到问题 $ jstack bash: jstack:commandnot found 原因 • 只安装了 JRE运行时环境没有安装 JDK 开发版 •PATH环境变量未配置 解决1. 安装 JDK 开发版 yuminstalljava-11-openjdk-devel.x86_64-y2. 配置 JAVA_HOMEexportJAVA_HOME/usr/lib/jvm/java-11-openjdkexportPATH$JAVA_HOME/bin:$PATH7.2 权限不足问题 $ jstackpidAttaching to process IDpid... Error: Attaching to processpidfailed 原因 • 当前用户没有权限查看该进程 • 进程属于其他用户如 root 解决 • 切换到进程所有者用户 • 或使用 sudosudojstackpid7.3 进程已终止问题 $ jstackpidAttaching to process IDpid... No such process 原因 • 进程已退出或被杀死 解决 • 确认进程还在运行jps 或ps-ef|grepjava• 重新启动 Java 应用 • 如果问题已发生在启动时添加 JVM 参数以便诊断八、项目中的应用场景8.1 云悦智销项目中的使用在生产环境部署云悦智销项目后1. CPU 占用100% →top-H-ppid找线程 → jstack 查看该线程堆栈 → 定位到具体代码行2. 内存持续增长几天后 OOM → jmap-heap看 Old 区使用率 → jmap-histo:live看对象分布 → jmap-dump生成堆转储 → MAT 分析找到泄漏原因3. 用户反馈页面卡顿 → jstack 查看是否有大量线程 BLOCKED → 排查数据库锁或同步锁4. 线程池监控 → jstack 查看线程池线程状态 → 是否有大量 WAITING 或 BLOCKED8.2 推荐 JVM 启动参数# 在启动 Java 应用时添加以下参数便于线上排查java-jarapp.jar\-XX:HeapDumpOnOutOfMemoryError\# OOM 时自动 dump-XX:HeapDumpPath/data/heap/\# dump 文件路径-Xms2g-Xmx2g\# 固定堆大小-Xmn512m\# 新生代大小-XX:UseG1GC\# G1 垃圾回收器-XX:PrintGCDetails\# 打印 GC 详情-XX:PrintGCDateStamps\# GC 时间戳-Xloggc:/data/gc/gc.log\# GC 日志路径一句话总结安装 jstack 和 jmap 的命令很简单yum install java-*-openjdk-devel但真正重要的是掌握它们的排查方法。jstack 用来分析线程问题CPU 高、死锁、卡顿jmap 用来分析内存问题OOM、内存泄漏。
Linux jstack 与 jmap 命令安装与实战
Linux jstack 与 jmap 命令安装与实战指南本文是云悦智销项目后端运维技术栈的一部分。在部署 Java 项目后jstack 和 jmap 是排查线上问题的必备工具。本文系统讲解如何在 Linux 服务器上安装这两个命令以及基本的排查使用方法。目录jstack 与 jmap 简介安装准备安装 JDK 开发版获取 jstack 和 jmap验证安装jstack 命令实战jmap 命令实战常见问题排查项目中的应用场景一、jstack 与 jmap 简介1.1 两个命令的作用┌──────────┬──────────────────────────────────────────────────────────┐ │ 命令 │ 作用 │ ├──────────┼──────────────────────────────────────────────────────────┤ │ jstack │ Java Stack Trace — 查看 Java 进程的线程堆栈信息 │ │ │ │ │ │ 应用场景 │ │ │ • 线程死锁Deadlock │ │ │ • 线程阻塞Blocked │ │ │ • 线程大量 WAITING等待锁 │ │ │ • CPU 占用高的线程定位 │ │ │ • 线程池状态分析 │ │ │ │ │ │ 输出线程状态、调用栈、等待的锁、持有的锁 │ ├──────────┼──────────────────────────────────────────────────────────┤ │ jmap │ Java Memory Map — 查看 Java 进程的堆内存分布 │ │ │ │ │ │ 应用场景 │ │ │ • 内存泄漏排查 │ │ │ • 对象数量统计 │ │ │ • 生成堆转储文件heap dump用于 MAT/VisualVM 分析 │ │ │ • 查看堆内存使用率 │ │ │ │ │ │ 输出对象数量、内存分布、堆转储文件 │ └──────────┴──────────────────────────────────────────────────────────┘ 一句话 jstack → 看线程CPU 高、卡顿、死锁 jmap → 看内存内存溢出、内存泄漏1.2 命令对比┌──────────────┬─────────────────────────┬─────────────────────────┐ │ 维度 │ jstack │ jmap │ ├──────────────┼─────────────────────────┼─────────────────────────┤ │ 关注点 │ 线程状态 │ 内存分配 │ │ 触发场景 │ CPU100%、线程卡顿 │ OOM、内存持续增长 │ │ 输出文件 │ 文本日志 │ 二进制.hprof 文件 │ │ 影响性能 │ 几乎无影响 │ 生成 dump 时有短暂停顿 │ │ 常用参数 │-l-m-f│-heap-histo-dump│ └──────────────┴─────────────────────────┴─────────────────────────┘二、安装准备2.1 为什么需要安装问题 Linux 服务器上默认只安装了 JREJava Runtime Environment JRE 不包含 jstack、jmap 等诊断工具 解决 需要安装 JDKJava Development Kit的 devel 版本 开发版运行时 诊断工具 开发工具2.2 检查系统环境# 1. 查看 Linux 发行版cat/etc/os-release# 或lsb_release-a# 2. 查看当前 Java 版本java-version# 3. 查看已安装的 Java 包rpm-qa|grepjava# 4. 查看 jstack/jmap 是否已存在jstack--help# 如果提示 command not found说明未安装jmap-h# 同上2.3 系统环境信息┌────────────┬────────────────────────────────────────┐ │ 操作系统 │ CentOS7/8、RHEL、Ubuntu │ │ Java 版本 │ JDK1.8/11/17│ │ 包管理器 │ yumCentOS/RHEL │ │ │ apt-getUbuntu/Debian │ └────────────┴────────────────────────────────────────┘三、安装 JDK 开发版获取 jstack 和 jmap3.1 CentOS/RHEL 方式yum# 步骤 1切换到 root 用户suroot# 步骤 2查看可用的 Java 版本yum list--showduplicate|grepjava# 或更精确的搜索yum list--showduplicate|grep-ijava.*jdk# 步骤 3安装对应版本的 JDK 开发版# 以 JDK 11 为例yuminstalljava-11-openjdk-devel.x86_64-y# 如果是 JDK 1.8yuminstalljava-1.8.0-openjdk-devel.x86_64-y# 如果是 JDK 17yuminstalljava-17-openjdk-devel.x86_64-y3.2 Ubuntu/Debian 方式apt-get# 步骤 1更新包列表sudoapt-getupdate# 步骤 2查看可用的 Java 版本apt-cachesearch openjdk# 步骤 3安装 JDK 开发版# JDK 11sudoapt-getinstallopenjdk-11-jdk-y# JDK 1.8sudoapt-getinstallopenjdk-8-jdk-y# JDK 17sudoapt-getinstallopenjdk-17-jdk-y3.3 安装命令流程图安装流程 yum list--showduplicate→ 查看所有可用版本 │ ├──grep-ijava*→ 过滤 Java 相关包 │ └── 找到对应版本 → 如 java-11-openjdk-devel.x86_64 │ yuminstalljava-11-openjdk-devel.x86_64-y│ └── 安装完成3.4 各版本对比┌────────────────────────┬──────────┬──────────┬──────────┐ │ 包名 │ JDK 版本 │ 支持年份 │ 推荐度 │ ├────────────────────────┼──────────┼──────────┼──────────┤ │ java-1.8.0-openjdk │ JDK8│2014│ ⭐⭐⭐⭐ │ │ java-11-openjdk │ JDK11│2018│ ⭐⭐⭐⭐⭐ │ │ java-17-openjdk │ JDK17│2021│ ⭐⭐⭐⭐ │ └────────────────────────┴──────────┴──────────┴──────────┘ 云悦智销项目推荐使用 JDK11企业级长期支持版本四、验证安装4.1 检查 jstack# 方法 1查看帮助信息jstack--help# 方法 2查看版本jstack-version# 成功标志显示帮助信息或版本号# 失败标志command not found4.2 检查 jmap# 方法 1查看帮助信息jmap-h# 方法 2查看版本jmap-version# 成功标志显示帮助信息或版本号# 失败标志command not found4.3 完整验证脚本#!/bin/bash# verify_jdk.sh - 验证 JDK 安装echo JDK 安装验证 # 1. 检查 javaecho1. Java 版本java-versionecho# 2. 检查 javac需要开发版才有的编译器echo2. javac 版本javac-versionecho# 3. 检查 jstackecho3. jstack 命令jstack--help21|head-3||echojstack 未安装echo# 4. 检查 jmapecho4. jmap 命令jmap-h21|head-3||echojmap 未安装echo# 5. 检查 JAVA_HOMEecho5. JAVA_HOMEecho$JAVA_HOMEechoecho 验证完成 五、jstack 命令实战5.1 基本用法# 语法jstack[options]pid# 常用选项# -l 打印锁的额外信息锁状态、等待队列# -m 打印 Java 和本地C/C帧的混合栈# -f 输出所有线程的栈追踪# -h 打印帮助信息5.2 实战 1查看线程状态# 步骤 1查找 Java 进程 PIDjps-l# 列出所有 Java 进程ps-ef|grepjava# 或用 ps 命令# 步骤 2使用 jstack 查看线程堆栈jstackpid# 基本查看jstack-lpid# 带锁信息查看jstack-mpid# 含本地帧# 输出示例pool-1-thread-1#15 prio5 os_prio0 tid0x00007f...java.lang.Thread.State: RUNNABLE at com.example.OrderService.queryOrder(OrderService.java:50)at com.example.OrderController.list(OrderController.java:30)...5.3 实战 2排查死锁# 查看死锁jstack 会自动检测jstack-lpid|grep-A5Deadlock# 如果存在死锁输出类似Thread-A#10 daemon prio5 os_prio0 tid0x00007f...java.lang.Thread.State: BLOCKED(on object monitor)at com.example.LockTest.methodA(LockTest.java:20)- waiting to lock0x00000006c0e00d80(a java.lang.Object)Thread-B#11 daemon prio5 os_prio0 tid0x00007f...java.lang.Thread.State: BLOCKED(on object monitor)at com.example.LockTest.methodB(LockTest.java:35)- waiting to lock0x00000006c0e00e00(a java.lang.Object)Found one Java-level deadlock:Thread-A:waiting to lock monitor 0x00007f...(object 0x00000006c0e00e00)whichis held byThread-BThread-B:waiting to lock monitor 0x00007f...(object 0x00000006c0e00d80)whichis held byThread-A5.4 实战 3排查 CPU 高# 步骤 1找到 CPU 占用高的进程top-H-ppid# 查看该进程下所有线程的 CPU 占用# 步骤 2找到 CPU 最高的线程 PID十进制# 假设线程 ID 为 12345# 步骤 3转换为十六进制printf%x\n12345# 输出3039# 步骤 4在 jstack 输出中搜索该十六进制线程 IDjstackpid|grep-A203039# 输出示例pool-1-thread-1#15 prio5 os_prio0 tid0x00007f...java.lang.Thread.State: RUNNABLE at com.example.OrderService.queryOrder(OrderService.java:50)at com.example.OrderController.list(OrderController.java:30)5.5 线程状态速查┌────────────────┬────────────────────────────────────────────┐ │ 线程状态 │ 含义 │ ├────────────────┼────────────────────────────────────────────┤ │ RUNNABLE │ 正在运行或等待 CPU 调度 │ │ BLOCKED │ 等待获取监视器锁synchronized 锁 │ │ WAITING │ 无限期等待其他线程执行如 Object.wait() │ │ TIMED_WAITING │ 有限期等待如 Thread.sleep(time) │ │ NEW │ 线程刚创建尚未 start()│ │ TERMINATED │ 线程已执行完成 │ └────────────────┴────────────────────────────────────────────┘ 常见异常 • 大量 BLOCKED → 锁竞争严重考虑优化锁粒度 • 大量 WAITING → 线程池可能等待任务正常 • 大量 TIMED_WAITING → 线程在sleep或等待超时 • RUNNABLE 长时间不释放 → 可能有死循环或复杂计算5.6 jstack 常用命令汇总# 查看指定进程的线程状态jstack12345# 查看线程堆栈并保存文件jstack12345thread_dump.txt# 查看带锁信息的线程状态jstack-l12345# 持续监控每 1 秒输出一次共 10 次foriin{1..10};dojstack12345sleep1donethread_monitor.log# 查看 Java 本地栈jstack-m12345六、jmap 命令实战6.1 基本用法# 语法jmap[options]pid# 常用选项# -heap 打印堆内存配置和使用情况# -histo[:live] 打印堆中对象统计:live 只统计存活对象# -dump:formatb,filefile 生成堆转储文件# -finalizerinfo 打印等待回收的对象6.2 实战 1查看堆内存使用# 查看堆内存配置和使用情况jmap-heappid# 输出示例Heap Configuration: MinHeapFreeRatio40MaxHeapFreeRatio70MaxHeapSize2147483648(2048.0MB)NewSize713031680(680.0MB)OldSize1434451968(1368.0MB)Heap Usage: NEW generation(Eden 1Survivor): Eden Space: capacity671088640(640.0MB)used438536192(418.17MB)free232552448(221.83MB)65.34905916213989% used OLD generation: capacity1434451968(1368.0MB)used1234567890(1177.26MB)free199884078(190.74MB)86.06494242983903% used6.3 实战 2查看对象统计# 查看堆中各类对象的数量和大小jmap-histopid# 只看存活对象jmap-histo:livepid# 输出示例# Class Objects Size ByteCode1: byte[]1234569876549876542: java.lang.String56789123456712345673: com.example.Order2345623456782345678...6.4 实战 3生成堆转储# 生成堆转储文件用于后续分析jmap-dump:formatb,fileheapdump.hprofpid# 只 dump 存活对象jmap -dump:live,formatb,fileheapdump.hprofpid# 说明# • heapdump.hprof 文件可能很大几百 MB 到几个 GB# • 生成时 JVM 会暂停几秒到几十秒STW# • 用 MAT (Memory Analyzer Tool) 或 VisualVM 打开分析6.5 内存问题分析流程内存问题排查流程 JVM 内存持续增长 │ jmap-heappid← 查看堆内存使用率 │ 如果 Old 区使用率80% │ jmap-histo:livepid← 查看哪类对象最多 │ 如果发现某对象数量异常 │ jmap -dump:live,formatb,fileheapdump.hprofpid│ 下载 hprof 文件 → MAT / VisualVM 分析 │ 找到内存泄漏原因七、常见问题排查7.1 jstack/jmap 命令找不到问题 $ jstack bash: jstack:commandnot found 原因 • 只安装了 JRE运行时环境没有安装 JDK 开发版 •PATH环境变量未配置 解决1. 安装 JDK 开发版 yuminstalljava-11-openjdk-devel.x86_64-y2. 配置 JAVA_HOMEexportJAVA_HOME/usr/lib/jvm/java-11-openjdkexportPATH$JAVA_HOME/bin:$PATH7.2 权限不足问题 $ jstackpidAttaching to process IDpid... Error: Attaching to processpidfailed 原因 • 当前用户没有权限查看该进程 • 进程属于其他用户如 root 解决 • 切换到进程所有者用户 • 或使用 sudosudojstackpid7.3 进程已终止问题 $ jstackpidAttaching to process IDpid... No such process 原因 • 进程已退出或被杀死 解决 • 确认进程还在运行jps 或ps-ef|grepjava• 重新启动 Java 应用 • 如果问题已发生在启动时添加 JVM 参数以便诊断八、项目中的应用场景8.1 云悦智销项目中的使用在生产环境部署云悦智销项目后1. CPU 占用100% →top-H-ppid找线程 → jstack 查看该线程堆栈 → 定位到具体代码行2. 内存持续增长几天后 OOM → jmap-heap看 Old 区使用率 → jmap-histo:live看对象分布 → jmap-dump生成堆转储 → MAT 分析找到泄漏原因3. 用户反馈页面卡顿 → jstack 查看是否有大量线程 BLOCKED → 排查数据库锁或同步锁4. 线程池监控 → jstack 查看线程池线程状态 → 是否有大量 WAITING 或 BLOCKED8.2 推荐 JVM 启动参数# 在启动 Java 应用时添加以下参数便于线上排查java-jarapp.jar\-XX:HeapDumpOnOutOfMemoryError\# OOM 时自动 dump-XX:HeapDumpPath/data/heap/\# dump 文件路径-Xms2g-Xmx2g\# 固定堆大小-Xmn512m\# 新生代大小-XX:UseG1GC\# G1 垃圾回收器-XX:PrintGCDetails\# 打印 GC 详情-XX:PrintGCDateStamps\# GC 时间戳-Xloggc:/data/gc/gc.log\# GC 日志路径一句话总结安装 jstack 和 jmap 的命令很简单yum install java-*-openjdk-devel但真正重要的是掌握它们的排查方法。jstack 用来分析线程问题CPU 高、死锁、卡顿jmap 用来分析内存问题OOM、内存泄漏。