一、概述
我们在做性能分析的时候,知识、经验是关键基础,数据是依据,工具是运用知识处理数据的手段。这里说的数据包括:运行参数、运行日志、异常堆栈、GC日志、线程快照(threaddump/javacore 文件)、堆转储快照(heapdump/hprof 文件)等。
本文只讨论JDK8的常用参数及工具。
二、JVM 参数类型
参数类型大概可以分为三类:
- 标准参数
- X参数
- XX参数
1、标准参数
JVM各个版本基本上不变的参数
举栗子:
-help
-server
-client
-version
-showversion
-cp
-classpath
2、-X 参数
一般用的不多,不同版本的JVM可能有变化
举栗子:-Xint
:完全解释执行,不会转换成本地代码
-Xcomp
:第一次使用就编译成本地代码,第一次比较慢
-Xmixed
:混合模式,JVM自己来决定是否编译成本地代码
3、-XXX 参数
非标准化参数,相对不太稳定,主要用于JVM调优和Debug,主要分为Boolean与非Boolean两种类型
3.1、Boolean 类型
格式:-XX:[+-]
表示启用或者禁用name属性
比如:
-XX:+UseConcMarkSweepGC
启用CMS垃圾回收器-XX:+UseG1GC
启用G1垃圾回收器
3.2、非 Boolean 类型
格式:-XX:=
表示name的属性的值是value
比如:
-XX:MaxGCPauseMilis=500
(GC最大停顿时间为500毫秒)XX:GCTimeRatio=19
-Xmx -Xms
-Xms
等价于-XX:InitialHeapSize
(初始化堆大小)- -
-Xms
等价于-XX:MaxHeapSize
(最大堆大小)
三、运行时 JVM 参数查看(最关键)
-XX:+PrintFlagsInitial
(初始值)-XX:+PrintFlagsFinal
(最终值)
列表内容
- =表示默认值
- :=被用户或JVM修改后的值
保存成文本下载下来大概有700多个参数
-XX:+UnlockExperimentaIVMOptions
(解锁实验参数才能赋值)-XX:+UnlockDiagnosticVMoptions
(解锁诊断参数)-XX:+PrintCommandLineFlags
(打印命令行参数)
1、jps(JVM Process Status Tool)
虚拟机进程状态工具,即可查看运行态的Java进程,使用频度最高的JDK命令行工具之一,因为其他工具大多需要输入它查询到LVMID(Local Virtual machine Identifier)来确定监控哪一个进程
jps命令格式:
$jps [ options ] [ hostid ]$
jps工具主要选项:
选项 | 作用 |
---|---|
-q |
只输出LVMID,省略类名 |
-m |
输出JVM Main函数的参数 |
-l |
输出类名,如果是JAR,输出其路径 |
-v |
输出JVM启动参数 |
举栗子:
查看运行java进程PID
jps -l
查看完全类名
官方参考链接:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
2、jinfo(Configuration Info for Java)
JVM配置信息工具,可实时查看和调整JVM的各项参数
命令格式:
$jinfo [ option ] pid$
查看运行中java进程的参数
jinfo -flag name pid
:当前设置的参数jin -flags name pid
:赋值的参数
举栗子:
查看最大内存
查看垃圾回收器,是否启用
3、jstat(JVM Statistics Monitoring Tool)
监控JVM各种运行状态信息的命令行工具,可以监控JVM中的类加载、内存、GC、JIT编译等运行数据
命令格式:
$jstat [ generalOption | outputOptions vmid [ interval[s|ms] [ count ] ]$
举栗子:
-class
类加载器-compiler
JIT-gc GC
状态-printcomplilation HotSpot
编译统计-gccapacity
各区大小-gccause
最后一次GC统计和原因-gcnew
年轻代状态-gcnewcapacity
年轻代大小-gcold
年老代大小-gcoldcapacity
年老代大小-gcutil GC
汇总统计
查看类装载,卸载数量,总空间以及类装载耗费的时间
官方参考链接:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
4、垃圾回收(性能监控非常有用)
实时动态查看内存变化
S0C
、S1C
、S0U
、S1U
:S0
和S1
的总量与使用量
-EC
、EU
:Eden
区总量与使用量OC
、OU
:Old
区总量与使用量MC
、MU
:Metaspace
区总量与使用量CCSC
、CCSU
:压缩类空间总量与使用量YGC
、YGCT
:YoungGC
的次数与时间FGC
、FGCT
:FullGC
的次数与时间GCT
:总的GC时间
5、JIT 编译
-complier
:输出JIT编译器编译过的方法、耗时等信息-printcomplilation
:输出已经被JIT编译的方法
6、jmap(Memory Map for Java)
JAVA内存映像工具,一方面用于生成堆转存储快照(heapdump或dump文件),另一方面可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前使用的垃圾收集器等
jmap命令格式:
$jmap [ options ] pid$
$jmap [ options ] executable core$
$jmap [ options ] [ pid ] server-id@ ] remote-hostname-or-IP$
jmap工具主要选项
选项 | 作用 |
---|---|
-dump |
生成JAVA堆转储快照 |
-finalize |
显示在F-Queue中等待finalizer线程执行finalize方法的对象 |
-heap |
显示堆详细信息,如使用的垃圾回收器、参数配置、分代状况等 |
-histo |
显示堆中对象的统计信息,包括类、实例数量、合计容量等 |
-permstat |
以ClassLoader为统计口径显示永久代的内存状态 |
-F |
强制生成dump快照 |
使用jmap生成dump文件
jmap打印内存直方图或heap信息
官方参考链接:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
7、jstack(Stack Track for Java)
JAVA堆栈跟踪工具,用于生成JVM当前时刻的线程快照(threaddump或javacore文件)。线程快照即当前JVM每一条线程正在执行的方法堆栈集合
主要用途:定位线程长时间停顿的原因,如:线程死锁、死循环、请求外部资源导致的长时间等待等。
jstack命令格式:
$jstack [ options ] pid$
$jstack [ options ] executable core$
$jstack [ options ] [ server-id@ ] remote-hostname-or-IP$
jstack工具主要选项:
选项 | 作用 |
---|---|
-F |
强制输出线程堆栈 |
-l |
除堆栈外,显示关于锁的附加信息 |
-m |
如果调用本地方法的话,可以显示C++的信息 |
使用jstack生成线程堆栈,jstack -l 23554 > test.threaddump
保存到文件
官方参考链接:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstack.html
举个小栗子:
Java程序抓最耗CPU的线程,可以通过这么几步:
- 通过
top
命令(top之后再按shift+H
可以显示线程)查看CPU使用率高的线程; - 将这个线程号转换为16进制,如:
printf %x
; - 使用
jps
查看服务器的Java进程号; - 使用
jstack [进程号]
打印当前的进程堆栈; - 从打印的信息中,找到第2步得到的线程号,看看这个线程在做什么。 不一定一次就能抓准线程状态,可以第1步时多记几个线程。
四、JVM 内存结构
- 堆区:S0和S1大小相同,同一个时间点上只有一个启用,另一个是空的
- 非堆区:操作系统的本地内存,独立于JVM的堆区之外的
- Metaspace:JDK8新特性
- CCS:启用短指针才会有
- CodeCache:把JAVA代码转换为Native代码存在此处,如果没有开启JIT编译,此处内存不存在
- CCS:启用短指针的时候存到此处