- 概述
- jstack 相关内容
- 背景
- 之前看了 jvm 相关 命令行工具
- jinfo
- jstat
- jmap
- jhat
- 它们的方向
- jvm 启动参数
- 内存资源
- gc 统计
- 堆栈快照
- 堆栈分析
- 堆栈? 不是只有堆吗?
- 是哈, 那栈呢?
- 环境
- OS
- win10
- Java
- 1.8.0_201
- demo
- Spring Boot
- 2.1.3
- shell
- win10 cmd
- 准备
- 一个 java 程序
- 我用的是基于 spring-boot 的 webmvc 程序
- 一个 controller 的 hello world
- jps
- 获取 java 程序 pid
- 最好有点 jvm 的知识
- 本人水平不咋样, 基本就是门槛边爬行的那种
1. jstack
- 概述
- jstack 简介
- jstack
- jvm 栈快照工具
- 栈
- jvm 线程活跃的地方
- 栈的内容
- 以线程为单位分割
- 每个线程都有自己的东西
- 各种寄存器, 存储线程专属信息
- 方法栈
- 每个线程, 在工作中, 会有自己一系列的方法调用
- 这些调用, 就以 栈 的形式, 在内存中存储
- 分类 - 这个不细说
- java 栈
- 存储 java 方法信息
- 本地方法栈
- 存储 本地方法 的信息
- 比如被 java 调用的 c 语言
- 两者关系
- 老实说, 我是不清楚的...
2. 命令
- 命令
> jstack <pid>
- 结果
- 这个结果有点复杂, 我慢慢说
3. 结果
- 概述
- 简单讲解 jstack 的结果
- 结果
- 命令执行时, 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 虚拟机的默认模式
- 需要后续追加
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
- 1041
- 目前有 1041 个 Global Reference
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
- nid=0x5110
- 原生系统线程 id
- 每个 java 线程, 都有一个对应 原生系统线程id
- waiting on condition
- 表示线程正处于 等待状态
- 具体条件没有说明
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
- 线程状态
- 这个暂时不在这里讲
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
- 线程状态...
- 下面的 堆栈信息
- 该线程正在执行的方法调用链
- 新的在上上面, 旧的在下面
3. 其他
- 命令行选项 -l
- 作用
- 增加内容, 线程的锁情况
- 副作用
- 会延长打印的时间
- 锁相关的内容, 后续再讲
ps
- ref
- jstack
- 官方文档
- 内容有些单薄
- JVM实用参数(一)JVM类型以及编译器模式
- 翻译的还行
- 2012 年的老文章...
- mix mode
- JNI学习三(Local references & Global references 以及JNI内存泄露)
- JNI 的讲解
- 这块我暂时不管了
- 4.5 jstack
- 讲得很清楚
- jstack 的 dump 信息
- java 线程状态
- 锁 相关
- JVM故障分析及性能优化系列之二:jstack生成的Thread Dump日志结构解析
- 写的很不错
- 对内容进行了科学的拆分
- 而且根据 线程所属组件, 明确分类
- 而且还是一个系列...
- 后头好好看下
- 三个实例演示 Java Thread Dump 日志分析
- 值得参考
- 虚拟机stack全分析
- 值得参考
- Java命令学习系列(二)——Jstack
- 问题们
- mix mode
- 线程状态
- 线程状态
- 状态转换
- 通过 jstack 分析与诊断 死锁问题
- 锁的原理
- 理解 线程状态
- 定位死锁线程
- 后续
- 可视化工具
尽量尝试解释清楚; 自己校对能力有限, 如果有错误欢迎指出