-
概述
- jstack 相关内容
-
背景
- 之前看了 jvm 相关 命令行工具
- jinfo
- jstat
- jmap
- jhat
- 它们的方向
- jvm 启动参数
- 内存资源
- gc 统计
- 堆栈快照
- 堆栈分析
- 堆栈? 不是只有堆吗?
- 是哈, 那栈呢?
- 之前看了 jvm 相关 命令行工具
-
环境
- OS
- win10
- Java
- 1.8.0_201
- demo
- Spring Boot
- 2.1.3
- Spring Boot
- shell
- win10 cmd
- OS
-
准备
-
一个 java 程序
- 我用的是基于 spring-boot 的 webmvc 程序
- 一个 controller 的 hello world
- 我用的是基于 spring-boot 的 webmvc 程序
-
jps
- 获取 java 程序 pid
-
最好有点 jvm 的知识
- 本人水平不咋样, 基本就是门槛边爬行的那种
-
1. jstack
-
概述
- jstack 简介
-
jstack
- jvm 栈快照工具
-
栈
- jvm 线程活跃的地方
-
栈的内容
- 以线程为单位分割
- 每个线程都有自己的东西
- 各种寄存器, 存储线程专属信息
- 方法栈
- 每个线程, 在工作中, 会有自己一系列的方法调用
- 这些调用, 就以 栈 的形式, 在内存中存储
- 分类 - 这个不细说
- java 栈
- 存储 java 方法信息
- 本地方法栈
- 存储 本地方法 的信息
- 比如被 java 调用的 c 语言
- 存储 本地方法 的信息
- 两者关系
- 老实说, 我是不清楚的...
- java 栈
-
- jvm 栈快照工具
2. 命令
-
命令
> jstack <pid>
-
结果
- 这个结果有点复杂, 我慢慢说
3. 结果
-
概述
- 简单讲解 jstack 的结果
-
结果
- 命令执行时, jvm 栈内的信息
- 主要是 方法调用 信息
- 命令执行时, jvm 栈内的信息
segment 1 - jvm 信息
-
片段
2020-04-11 19:20:35 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
-
内容
-
2020-04-11 19:20:35
- jstack 命令执行时间
-
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
- 64-Bit
- 64 位系统
- Server VM
- jvm 服务器模式
- 25.181-b13
- jvm 的 build 号
- mixed mode
- HotSpot 虚拟机的默认模式
- 需要后续追加
- HotSpot 虚拟机的默认模式
- 64-Bit
-
segment 2 - JNI global references
-
片段
# 这个位于 输出日志的 最下方 JNI global references: 1041
-
解释
- JNI global references: 1041
- JNI - Java Native Interface
- Java 的本地接口
- 负责调用与 其他语言交互
- global references
- JNI reference
- Local reference
- 本线程 native method 中的变量
- 返回 java 后自动释放
- Global Reference
- 多个线程, 多个方法中使用
- 需要手动创建, 释放
- Weak Global Reference
- 和 Global Reference 基本一致
- 不过有可能会被 GC
- Local reference
- JNI reference
- 1041
- 目前有 1041 个 Global Reference
- JNI - Java Native Interface
- JNI global references: 1041
segment 3: VM Periodic Task Thread 线程片段
-
片段
"VM Periodic Task Thread" os_prio=2 tid=0x000000003c4c5800 nid=0x5110 waiting on condition
-
解释
- "VM Periodic Task Thread"
- 线程名称
- 这个是 HotSpot 的监控进程
- 通过执行 周期性任务, 来获取 jvm 的各种信息
- 线程名称
- os_prio=2
- 系统进程优先级
- 这个和 操作系统 有关系
- 后面会讲到 java 线程优先级...
- 系统进程优先级
- tid=0x000000003c4c5800
- java 线程id
- 线程在 jvm 中的 id
- java 线程id
- nid=0x5110
- 原生系统线程 id
- 每个 java 线程, 都有一个对应 原生系统线程id
- 原生系统线程 id
- waiting on condition
- 表示线程正处于 等待状态
- 具体条件没有说明
- 表示线程正处于 等待状态
- "VM Periodic Task Thread"
segment 4: GC 线程片段
-
片段
# 这样类似的片段, 一共有 9 个 "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000031bb000 nid=0x1c54 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000031bd000 nid=0x3718 runnable ...
-
解释
- "GC task thread#0 (ParallelGC)"
- 线程名称
- GC 线程
- 编号为0
- 使用的是 ParallelGC
- 线程名称
- os_prio=0
- 系统进程优先级
- tid=0x00000000031bb000
- java 线程id
- nid=0x1c54
- 原生系统线程 id
- runnable
- 线程状态
- 这个暂时不在这里讲
- 线程状态
- "GC task thread#0 (ParallelGC)"
segment 5: 普通线程片段
-
片段
"http-nio-8080-ClientPoller-1" #45 daemon prio=5 os_prio=0 tid=0x000000003e78e800 nid=0x574 runnable [0x0000000040d8f000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method) at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296) at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278) at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) - locked <0x00000006768fe120> (a sun.nio.ch.Util$3) - locked <0x00000006768fe110> (a java.util.Collections$UnmodifiableSet) - locked <0x00000006768fdfc0> (a sun.nio.ch.WindowsSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:743) at java.lang.Thread.run(Thread.java:748)
-
解释
- "http-nio-8080-ClientPoller-1"
- 线程名称
#45
- 这个我找了好久, 也不知道叫啥
- 也不知道为啥有的线程有, 有的线程没有
- 甚至连 大小 规律, 都没有搞清楚
- 这个我找了好久, 也不知道叫啥
- daemon
- 守护线程
- 当前线程, 是一个守护线程
- 守护线程
- prio=5
- os_prio=0
- tid=0x000000003e78e800
- nid=0x574
- runnable
- 可执行状态
- [0x0000000040d8f000]
- 线程的 栈 起始地址
- 起始地址为 [0x0000000000000000]
- 这些通常是 jvm 的进程
- 它们需要与 操作系统打交道, 所以栈的起点在 本地方法栈
- 当然并非所有的 jvm 进程, 都是以 [0x0000000000000000] 为起始
- java.lang.Thread.State: RUNNABLE
- 线程状态...
- 下面的 堆栈信息
- 该线程正在执行的方法调用链
- 新的在上上面, 旧的在下面
- "http-nio-8080-ClientPoller-1"
3. 其他
- 命令行选项 -l
- 作用
- 增加内容, 线程的锁情况
- 副作用
- 会延长打印的时间
- 锁相关的内容, 后续再讲
- 作用
ps
-
ref
-
- 官方文档
- 内容有些单薄
-
- 翻译的还行
- 2012 年的老文章...
- mix mode
-
JNI学习三(Local references & Global references 以及JNI内存泄露)
- JNI 的讲解
- 这块我暂时不管了
- JNI 的讲解
-
- 讲得很清楚
- jstack 的 dump 信息
- java 线程状态
- 锁 相关
- 讲得很清楚
-
JVM故障分析及性能优化系列之二:jstack生成的Thread Dump日志结构解析
- 写的很不错
- 对内容进行了科学的拆分
- 而且根据 线程所属组件, 明确分类
- 而且还是一个系列...
- 后头好好看下
- 写的很不错
-
- 值得参考
-
- 值得参考
-
-
问题们
- mix mode
- 线程状态
- 线程状态
- 状态转换
- 通过 jstack 分析与诊断 死锁问题
- 锁的原理
- 理解 线程状态
- 定位死锁线程
-
后续
- 可视化工具