JVM全文
概述
- GUI,Graphical User Interface,图形化用户接口
- 命令行工具的局限
- 无法获取方法级别的分析数据,如方法间的调用关系、各方法调用次数和调用时间
- 分析数据通过终端输出,结果不够直观
jconsole
- 用于对JVM中内存、线程和类等的监控
- 命令行输入
jconsole
直接启动 - 检测死锁
Visual VM
- 显示虚拟机进程、进程的配置和环境信息 jps、jinfo
- 监视应用程序的CPU、GC、堆、方法区及线程的信息 jstat、jstack
- 远程连接
- JVM参数
- 生成dump文件
- dump文件比较
- 线程dump
- 抽样器,定位占用cpu的方法
- 过滤
MAT
- eclipse下的分析dump文件的工具
- 对象的所有信息,对象实例、成员变量、存储在栈中的基本数据类型值、堆中的其他对象的引用值
- 所有类信息,classloader、类名称、父类、静态变量
- CGRoot到所有的对象的引用路径
- 线程信息,线程调用栈及此线程的线程局部变量
TLS Thread Local Storage
- 浅堆和深堆
- 浅堆,不包括所引用部分的内存大小,对象本身占有的内存
- 深堆,当前对象被彻底回收能收回的内存大小;保留集,只能被对象A直接或间接访问到的所有对象的集合
- 对象实际大小,一个对象所能触及的所有对象的浅堆大小之和
- 查看线程信息
- 出引用,主动引用;入引用,被引用
扫描二维码关注公众号,回复:
13530570 查看本文章
- 支配树,对象实例间的支配关系,所有指向B的关系,都需要经过A,A是B的支配者
- A的子树(所有被A支配的对象集合)表示A的保留集,即为深堆
- 对象A支配对象B,那么对象A的直接支配者也支配对象B
- 支配树的边与对象引用图的边不直接对应
- 查看支配树关系
内存泄漏
- 严格意义上,还被使用,但是不需要;只有对象不再被程序使用到,但是GC又无法回收
- 宽泛意义上,实际上一些不太好的编码习惯导致对象的生命周期变得很长
- 分类
- 经常发生,发生内存泄漏的代码会被多次执行,执行一次,泄漏一次
- 偶然发生,在某些特定情况才会发生
- 一次性,发生内存泄漏的方法只会执行一次
- 隐式泄漏,一直占着内存不是放,直到执行结束
- 将元素存放进
hashset
后,修改了hashcode
导致不能找到这个元素
OQL语句
- 类似sql语句
- oql查询
select * from java.util.ArrayList
SELECT objects v.elementData FROM java.util.ArrayList v
//得到Picutre类型的保留集
select as retained set * from com.java.Picture
//当前地址开始找
select * from 0x79fa91040
//长度大于10
SELECT * FROM char[] s where s.@length > 10
//path的value值
SELECT toString(f.path.value) FROM java.io.File f
//list长度
SELECT v.elementData.@length FROM java.util.ArrayList v
复制代码
jProfiler
- 数据采集方式
- instrumentation 全功能模式,在class加载前,把相关功能代码写入到需要分析的
class的bytecode
中,对应用性能有所影响,一般配合filter使用,只对特定的类或包进行分析- simpling,样本统计,每隔一定时间将每个线程栈中方法栈的信息统计出来,但是一些数据(方法调用次数、执行时间)不能提供
- 内存监控
- 频繁创建的java对象,死循环、循环次数过多
- 存在大的对象,读取文件时,byte[]应该边读边写,否则会导致byte数组过大
- 存在内存泄漏,每次gc之后留下来的内存是在稳步上升的,存在内存泄漏问题
- 分析内存泄漏
- 出引用(主动引用);进引用(被引用)
- 引用关系
- 线程分析
- web容器的线程最大数,Tomcat的线程容量应该略大于最大并发数
- 线程阻塞
- 线程死锁
Arthas
- 阿尔萨斯,阿里巴巴
- 不需要远程连接,不需要配置监控参数,也可以对服务器上的项目进行性能监控
- 下载
curl -O https://arthas.aliyun.com/arthas-boot.jar
- 启动
java -jar arthas-boot.jar [pid]
- 退出客户端
quit
停止服务器端stop
- 浏览器方式访问
http://localhost:8563/
3658telent端口 - 查看log
cat ~/logs/arthas/arthas.log
指令
session
查看当前回话信息dashboard
展示当前进程信息,实时面板
//每隔1秒打印一次,打印5次
dashboard -i 1000 -n 5
复制代码
thread
线程信息
//查看id为1的线程
thread 1
//查看死锁的线程
thread -b
//统计5秒钟的各线程cpu的利用率
thread -i 5000
//按cpu占用率取前2
thread -n 2
复制代码
sysprop
jvm属性信息sysenv
环境变量heapdump ../jvisualvm/arthas.hprof
生成dump文件
//存活对象
heapdump --live ../jvisualvm/arthas.hprof
复制代码
sc com.java.*
打印加载的类信息
//输出加载的类的详细信息
sc -d com.java.*
//输出类的成员变量
sc -d -f com.java.*
复制代码
sm com.java.OOMTest
对应类的方法
//找到ma开头的方法
sm com.java.OOMTest ma*
//方法详细表述
sm -d com.java.OOMTest ma*
复制代码
jad com.java.OOMTest
对某个类反编译
//反编译某个方法
jad com.java.OOMTest main
复制代码
mc ../OOMTest.java
编译java文件retransform /Users/mzx/Desktop/java/jvm/jvm_program/com/java/Picture.class
加载进内存,替换当前类classloader
类的加载器
//树形结构查看
classloader -l
//统计信息
classloader -t
//指定加载器的加载的范围
classloader -c 18b4aac2
复制代码
monitor
方法执行监控,非实时返回指令;RT响应时间
//每隔1秒打印一次
monitor -c 1 com.java.Picture <init>
复制代码
watch
方法执行数据观测;深度表示内容的精细程度,如显示数组中的细节
//观测init方法的 参数和返回值 深度为2
watch com.java.Picture <init> "{params, returnObj}" -x 2
复制代码
trace
方法内部调用的路径,输出路径上每个节点的耗时
//只输出5次
trace -n 5 com.java.Picture <init>
复制代码
stack
方法被调用的路径
stack -n 5 com.java.Picture <init>
复制代码
tt
方法执行数据的时间隧道,记录下指定方法每次调用的入参和返回信息
tt -t -n 5 com.java.Picture <init>
复制代码
生成火焰图
- y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
- x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。
profiler
,默认为cpu的热点图
//开始
94 profiler start
//获取已采集的样本数量
95 profiler getSamples
//暂停
99 profiler stop
复制代码
- 浏览器查看网页
http://localhost:3658/arthas-output/20211211-165747.svg
Java Mission Control
- jmc
- jdk里没有,另外下载了下载地址
- 取样的时候,不是传统的代码植入,对应用的性能影响很小
- jfr,java flight recorder,收集性能数据
- 配置参数
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
,不配也正常,看jdk版本
其他
- 火焰图,直观展示调用栈中的CPU消耗瓶颈
Tprofiler
准确定位需要提供性能的代码,统计出指定时间段内,JVM的top method
,造成性能瓶颈的原因BTrace
安全可靠的动态跟踪分析工具TPS Transactions Per Second
服务器每秒处理的事务数QPS queries per second
每秒的响应请求数;每秒相应的查询次数