Java - JVM - visualvm 简介
-
概述
- 今天聊聊 visualvm
-
背景
-
之前简单聊了聊 JVM 的 命令行工具
- jinfo
- JVM 启动参数
- jstat
- JVM 的 堆内存 以及 gc 情况
- jmap
- 做 堆内存 的 dump
- jhat
- 分析堆内存 dump
- jstack
- 分析 线程的情况
- jinfo
-
问题
- 命令行工具, 还是有些问题的
- 命令行工具 没那么好看
- 截取的内容, 都是一个瞬间
- 无法做趋势的比对
- 有时候要抓住某个瞬间, 还真有点难
- 命令行工具, 还是有些问题的
-
解决
- 可以尝试用 图形工具, 来解决这些问题
- jmc
- 这个工具后面讲
- visualvm
- 这次就他了
- jconsole
- visualvm 是它的升级版, 所以就不聊它了
- jprofile
- 一款需要付费的软件, 暂时不提
- 据说很强大
- jmc
- 可以尝试用 图形工具, 来解决这些问题
-
-
环境
- OS
- win10
- Java
- 1.8.0_201
- demo
- Spring Boot
- 2.1.3
- Spring Boot
- shell
- win10 cmd
- OS
1. 准备
-
示例进程
- 随便起了个 spring-boot 的 webmvc 工程
- 写个 hello world 之类的就行
- 以下简称 demo
- 随便起了个 spring-boot 的 webmvc 工程
-
约定
- 后面只描述 本地执行 的结果
- visualvm 其实可以远程执行, 这个有兴趣的同学自己去研究吧
- 后面只描述 本地执行 的结果
2. visualvm
-
概述
- 简介 visualvm
-
visualvm
-
java 可视化管理, 维修, 剖析工具
- 可视化
- 没错, 他有图形界面
- 剖析
- 信息应该会 很全面吧
- 可视化
-
启动
-
图形启动
-
路径
$JAVA_HOME/bin/jvisualvm.exe
-
-
命令行启动
-
准备
- 确认 bin 目录在 classpath 里
-
命令
> jvisualvm
-
-
一打开我就懵逼了
- 东西挺多从什么地方说起呢?
- 当然是从 最简单的 说起了
- 东西挺多从什么地方说起呢?
-
-
1. 控件 - 应用程序
-
概述
- 简述 应用程序 控件
-
内容
- 本地
- 能看到 本地运行 的 JVM 名称
- 规律我也不填清楚
- visualvm 和 idea 都是显示程序名
- 我的 demo 程序, 则是用的 main 类全名...
- 规律我也不填清楚
- 右键菜单
- 打开
- 可以查看本地 内存 和 交换空间 的信息
- 添加
- jmx 连接
- jstatd 连接
- 属性
- 展示本地描述
- 打开
- 能看到 本地运行 的 JVM 名称
- 其他
- 水平有限, 就不瞎讲了
- 随缘补充
- 本地
-
输入
- 由应用程序控件分析, visualvm 大概可以接受四种类型的输入
- 本地
- 远程
- VM 核心 dump
- 快照
- 这些具体是什么, 我好像现在也解释不了
- 先随便选个 本地 的 JVM 看看
- 由应用程序控件分析, visualvm 大概可以接受四种类型的输入
-
右键菜单
-
操作
- 右键单击 JVM 实力, 弹出右键菜单
-
操作与现象
-
属性
- 打开后进入 属性窗口
- 名称
- 介绍
- 连接
- 直接 VM
- 本地 jvmstat
- 打开后进入 属性窗口
-
其他不说了
-
-
疑问
- 连接
- vm 和 jvmstat 有什么不同
- 连接
-
-
后续
- 连接类型
- 选用 本地 jvmstat
- 大多数程序都是这个类型...
- 选用 本地 jvmstat
- 连接类型
2. 控件 - 右侧主窗口
-
概述
- 简述 右侧主窗口
-
准备
- 双击之前启动的 demo 程序
- 右边立马出现一个 标签页
- 标签页下, 有 4 个子页面
- 我们一个一个看吧...
- 双击之前启动的 demo 程序
1. 概述
-
概述
- 概述页
-
内容
-
虚拟机名 与 pid
-
概述
- 进程信息
- pid
- 主机名
- JVM 信息
- JVM 的主类
- 就是 main 方法的位置
- 命令行参数
- JVM 名称版本
- Java 版本
- Java Home
- JVM 标志?
- JVM 的主类
- 进程信息
-
保存的数据
- 类型
- 线程 dump
- 堆 dump
- Profiler 快照
- 得知
- visualvm 可以捕捉这些类型
- 应用程序 右键菜单 就有选项, 可以创造这三种类型
- visualvm 可以捕捉这些类型
- 类型
-
参数
- JVM 参数
- 系统属性
-
2. 监视
-
CPU 监控
- 方式
- 实时监控
- 内容
- cpu
- cpu 使用
- 垃圾回收活动
- cpu
- 操作
- 鼠标移动到某个时间上, 会显示当时的占用率
- 方式
-
内存
- 方式
- 实时监控
- 内容
- 堆
- 当前容量
- 已经使用
- 最大容量
- metaspace
- 当前容量
- 已经使用
- 最大容量
- 堆
- 方式
-
类
- 方式
- 实时监控
- 内容
- 已装入的总量
- 已卸载的总数
- 共享的已装入数
- 共享的已卸载数
- 方式
-
线程
- 方式
- 实时监控
- 内容
- 活动线程
- 实时峰值
- 守护线程
- 已启动的线程?
- 方式
-
其他功能
-
触发 gc
- 图形
- 通常是那种 锯齿形
- 一次函数 的那种上升
- 一下垂直的下降
- gc 触发
- gc 触发确实可以提前那个下降
- 通常是那种 锯齿形
- 图形
-
堆 dump
-
3. 线程
-
线程统计
- 实时线程
- 守护线程
-
线程可视化
-
时间线
- 放大
- 缩短采集间隔
- 提高数据精度
- 但是会影响 jvm 性能
- 最小间隔 50ms
- 缩短采集间隔
- 缩小
- 和放大相反
- 最大间隔 30mins
- 适当
- 选了之后就没法调整了
- 但是具体精度是多少, 我也说不上来
- 我当时是 5mins
- 放大
-
筛选
- 条件
- 所有
- 活动
- 完成
- 条件
-
线程图表 一行
- 名称
- 线程名称
- 状态
- 每个时间段, 线程的状态
- 颜色 与 状态
- 运行 - 绿色
- 休眠 - 紫色
- 等待 - 黄色
- 驻留 - 橙色
- 监视 - 粉色
- 名称
-
-
其他操作
- 线程 dump
4. 抽样器(Sample)
-
概述
- visualvm 下的 抽取器
-
抽样器 vs 分析器(Profiler)
- 机制
- 抽样器
- 基于 dump, 周期性的抓取数据
- 分析器
- 基于 bytecode, 添加字节码, 从而监控所有方法的调用情况
- 抽样器
- 结果
- 抽样器
- 精度不如 分析器
- 性能影响小
- 分析器
- 精度较高
- 性能影响较大
- 特别是在 堆内存 上, 这俩的结果完全不同
- 抽样器 的 数值, 基本都要比 分析器 大
- 类数量
- 类占用空间
- 实例数
- 抽样器 的结果, 是 dump, 整个堆的一个复制
- 100% 的完全重现
- 分析器 的结果, 是 阶段性的结果
- 记录的时间起点, 是你开始分析的时刻, 到当前时间, 或者你停止分析的时刻
- 这是一个 增量 的记录
- 抽样器 的 数值, 基本都要比 分析器 大
- 抽样器
- 机制
-
CPU 抽样
-
设置
- 类
- 可以用 黑名单/白名单 的方式, 追踪具体的包
- 抽样率
- 可以调整抽样的精度
- 类
-
基本操作
- 开启
- 单击 抽样 后的 CPU 按钮
- 单击后 状态 变为 正在进行 CPU 抽样
- 下面的 标签页, 出现内容
- 内容会随 结果刷新 的时间变动
- 单击 抽样 后的 CPU 按钮
- 停止
- 单击 停止 按钮
- 暂停
- 暂停刷新
- 但是抽样应该在继续
- 刷新
- 前提
- 暂停抽样
- 结果
- 立即更新抽样数据
- 前提
- 排序
- 结果的表格, 支持按照列排序
- 正序
- 倒叙
- 结果的表格, 支持按照列排序
- 筛选
- 结果的表格, 支持
- 最下面
- 结果的表格, 支持
- 开启
-
CPU 样例 - 方法维度
-
数据 - 行
- 方法
- 统计的 方法
- 自用时间 百分比
- 线程自用时间, 占 总共自用时间 的百分比
- 自用时间
- 自用
- 只包含 该行方法 的时间
- 不包含 调用/执行其他方法 花费的时间
- 时间
- 包含
- cpu 时间
- 等待
- 休眠
- 包含
- 自用
- 自用时间(CPU)
- 自用 cpu 时间
- 总时间
- 包含了 该行方法 和 调用/执行其他方法 花费的时间
- 总时间(CPU)
- 包含了 该行方法 和 调用/执行其他方法 花费的 CPU时间
- 样例
- 调用方法的最低次数
- 自定义
- 每行显示的数据, 可以做 自定义, 这个我就不下车了
- 方法
-
操作
- 快照
- 可以生成 snapshot
- 快照后面集中再讲
- 可以生成 snapshot
- 快照
-
-
线程 CPU 时间 - 线程维度
-
统计
- 线程数
- 总 CPU 时间
-
数据 - 行
- 线程名称
- 线程名称
- 线程 CPU 时间 [%]
- 线程占用的 CPU 时间百分比
- 总时间
- 线程占用的 CPU 时间百分比
- 线程 CPU 时间 [毫秒]
- 线程占用的 CPU 总时间
- 数据后面的 % 我没看懂
- 线程 CPU 时间 [毫秒]/秒
- 线程上一秒 占用的 CPU 时间
- 线程名称
-
操作
- 增量
- 显示当前时刻开始的增量统计
- 再点一下又切回总时间统计
- 增量
-
-
-
内存抽样
-
设置
- 抽样率
-
基本操作
- 开启
- 单击 内存 按钮
- 停止
- 单击 停止 按钮
- cpu 和 内存 抽样可以不同时进行
- 当前查看哪个, 停止的时候, 就停止哪个
- 单击 停止 按钮
- 暂停
- 同 cpu抽样
- 刷新
- 同 cpu抽样
- 排序
- 同 cpu抽样
- 筛选
- 同 cpu抽样
- 开启
-
堆柱状图
-
统计
- 类
- 实例
- 字节
-
数据 - 行 - 没啥好解释的, 比 jhat 友好多了...
- 类名
- 字节[%]
- 字节
- 实例数
-
操作
- 增量
- 查看从现在开始的 增量
- 快照
- 产生 快照
- 后面再讲
- 执行 GC
- 堆 dump
- 后面再讲
- 增量
-
-
每个线程分配
-
统计
- 线程
- 已分配的总字节数
-
数据 - 行
- 线程名称
- 已分配的字节 [%]
- 已分配的字节
- 已分配的字节 /秒
-
操作
- 增量
- 执行 GC
- 堆 dump
-
-
5. 分析器
-
概述
- 简述 分析器
-
CPU 分析器
-
设置
-
从类启动性能分析
- 启动
- 调用列表里的类代码, 会启动性能分析
- 只是个 开关
- 具体决定要分析那些类, 由后面决定
- 格式
# 一行一个范围 # 1. 某个类 com.demo.Class # 2. 某个包中类 com.demo.* # 3. 某包中类及其子类 com.demo.** # 4. 所有类 空白, 什么都不写
- 启动
-
分析新的可运行对象
- 会对新线程进行分析
-
黑白名单
- 要分析/不分析的类
- 注意上面选的是 黑名单 还是 白名单
- 要分析/不分析的类
-
预设
- 这个我也没怎么看
-
-
基本操作
- 开启
- 单击 性能分析 后的 CPU 按钮
- 单击后 状态 变为 正在进行 CPU 分析
- 下面的 标签页, 出现内容
- 内容会随 结果刷新 的时间变动
- 单击 性能分析 后的 CPU 按钮
- 停止
- 单击 停止 按钮
- 自动更新结果
- 选中后, 会自动刷新
- 补选中, 刷新会停止, 但是分析应该在继续
- 立即更新结果
- 前提
- 自动跟新结果 未选中
- 结果
- 立即更新分析数据
- 前提
- 垃圾回收并更新结果
- 这个不懂
- 重置收集的结果缓冲区
- 清空之前的结果
- 重新开始收集
- 快照
- 产生快照
- 导出至
- 输出一个 xml
- 记录当前的情况
- 输出一个 xml
- 将当前视图另存为图像
- 输出一个图片
- 记录当前的情况
- 输出一个图片
- 排序
- 结果的表格, 支持按照列排序
- 正序
- 倒叙
- 结果的表格, 支持按照列排序
- 筛选
- 结果的表格, 支持
- 最下面
- 结果的表格, 支持
- 开启
-
数据 - 行
- 热点 - 方法
- 被统计的方法名
- 自用时间[%]
- 略
- 自用时间
- 略
- 总时间
- 略
- 调用
- 方法调用的次数
- 热点 - 方法
-
-
内存分析器
-
设置
- 记录内容
- 分析对象分配
- 只记录对象分配
- 分析对象分配和 GC
- 记录对象的整个 生命周期
- 分析对象分配
- 全部跟踪
- 以 n 个对象为一组跟踪
- 不太懂
- 记录分配栈跟踪
- 不太懂
- 预设
- 不太懂
- 记录内容
-
基本操作
- 同 CPU 分析器
-
数据 - 行
- 类名 - 活动的分配对象
- 略
- 活动字节[%]
- 略
- 活动字节
- 略
- 活动对象
- 略
- 年代数
- 存活的垃圾回收次数
- 类名 - 活动的分配对象
-
注意
- CPU 分析 和 内存分析, 不能同时开启
-
ps
-
ref
- 官方引导
- 感觉效果不是很好
- Profiling Vs. Sampling in Java’s VisualVM
- sample vs profiler
- Spring Boot+Spring Cloud+Vue+Element项目实战
- 一个实战
- 网易的老哥通过言传身教, 告诉我们, 他们自己的 json 模块性能不好
- 更倒霉的是, 最后居然换上了 fastjson...
- 一个实战
- 【Java VisualVM】使用 VisualVM 进行性能分析及调优
- 一个更加走心的实战
- VisualVM and Self Time
- self time 的解释
- 为数不多的解释
- 其实, 把鼠标悬停在表头, 自己就会出现解释
- 最后知道真相的我眼泪掉下来
- self time 的解释
- 官方引导
-
疑问
- 问题1
- 共享的装入卸载, 如何触发
- 问题2: 线程统计里的 已启动总数
- 本质上还是不知道 四个量 之间的关系
- 问题3: 线程状态, 驻留, 监视
- 这俩状态我搞不懂
- 问题4: sampler 和 profiler 的 堆内存数据
- 这俩数据有什么区别, 内容为什么不一样
- 问题1
-
后续
- 啰嗦半天总算把最基本的东西说完了...
- 基本就是记下了个流水账
- 缺失的东西是 各项指标的意义, 以及具体的使用场景
- 后续内容
- 快照
- visualvm 有各种快照, 这里来不及说了
- 插件
- 插件的安装, 其实很简单, 自己看看就会了, 我也不废话了
- 快照
- 啰嗦半天总算把最基本的东西说完了...
尽量尝试解释清楚; 自己校对能力有限, 如果有错误欢迎指出