基于jdk1.8的Java服务监控和性能调优

JVM的参数类型

X参数

  • 非标准参数
  • -Xint: 解释执行
  • -Xcomp: 第一次使用就编译成本地代码
  • -Xmixed: JVM自己来决定是否编译成本地代码

默认使用的是mixed mode

基于jdk1.8的Java服务监控和性能调优_第1张图片

用的不多, 只需要做了解, 用的比较多的是XX参数

XX参数

  • 非标准化参数
  • 相对不稳定
  • 主要用来JVM调优和Debug

Boolean:

  • 格式: -XX:[+-] 表示启用或禁用name属性
  • 比如: -XX:+UseConcMarkSweepGC , 表示启用了CMS垃圾收集器
  • -XX:+UseG1GC , 表示启用了G1垃圾收集器

非Boolean类型:

  • 格式: -XX:=表示name属性的值是value
  • 比如:-XX:MaxGCPauseMillis=500 , GC的最大停顿时间为500ms
  • -XX:GCTimeRatio=19, 表示垃圾回收时间最长不会超过总运行时间的 1/20

-Xmx -Xms

  • 不是X参数, 而是XX参数

-Xms等价于-XX:InitialHeapSize

-Xmx等价于-XX:MaxHeapSize

查看JVM运行时参数

常见参数

  • -XX:+PrintFlagsInitial , 查看程序运行的初始值
  • -XX:+PrintFlagsFinal , 查看最终的值, 因为初始值可能会被修改(命令或程序修改)
  • -XX:+UnlockExperimentalVMOptions , 解锁实验参数, 因为JVM中并不是所有的参数都可以直接赋值, 需要先使用这个参数才可以进行赋值
  • -XX:+UnlockDiagnosticVMOptions , 解锁诊断参数
  • -XX:+PrintcommandLineFlags , 打印命令行参数

使用示例: java -XX:+PrintFlagsFinal -version

这里查看的仅仅是调用java命令的当前进程的配置值, 后续会使用jinfo查看启动后的进程的参数配置

基于jdk1.8的Java服务监控和性能调优_第2张图片

jps

可以根据网站查询具体的jps使用方法:

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html#CHDCGECD

包含JVM命令的所有使用方法: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html

jps

基于jdk1.8的Java服务监控和性能调优_第3张图片

jps -l

基于jdk1.8的Java服务监控和性能调优_第4张图片

jinfo

查看最大内存:

jinfo -flag MaxHeapSize 

基于jdk1.8的Java服务监控和性能调优_第5张图片

查看垃圾回收器:

jinfo -flag UseConcMarkSweepGC 
jinfo -flag UseG1GC 
jinfo -flag UseParallelGC 

基于jdk1.8的Java服务监控和性能调优_第6张图片

可以看出使用的是并行回收的垃圾回收器

jstat查看JVM统计信息

命令格式:

基于jdk1.8的Java服务监控和性能调优_第7张图片

options :

  • -class: 查看类加载信息
  • -compiler: 查看编译信息
  • -gc: 查看GC信息
  • -printcompilation: 查看JIT编译信息

类装载

# 1000 输出间隔1000ms 10 表示输出总次数为10次
jstat -class  1000 10

基于jdk1.8的Java服务监控和性能调优_第8张图片

垃圾收集

-gc , -gutil , -gccause , -gcnew , -gcold

所有的输出含义都可以在上文中提到的网站中进行查询

基于jdk1.8的Java服务监控和性能调优_第9张图片

  • Young区:
    • S0C:当前 Survivor Space 0 的容量(kB)。
    • S1C:当前 Survivor Space 1 的容量(kB)。
    • S0U:Survivor Space 0 的利用率(kB)。
    • S1U:Survivor Space 1 的利用率(kB)。
    • EC:当前 Eden Space 的容量(kB)。
    • EU :Eden Space 的利用率(kB)。
  • Old区:
    • OC:当前 Old Space 的容量(kB)。
    • OU:Old Space 的利用率(kB)。
  • MC:Metaspace 的容量(kB)。
  • MU:Metaspace 的利用率(kB)。
  • CCSC:压缩类空间的容量(kB)。
  • CCSU:压缩类空间的使用情况(kB)。
  • YGC:Young Generation 垃圾回收事件的数量。
  • YGCT:Young Generation 垃圾回收时间。
  • FGC:Full GC 事件的数量。
  • FGCT:Full GC 时间。
  • GCT:垃圾回收总时间。

JVM内存结构:

基于jdk1.8的Java服务监控和性能调优_第10张图片

JIT编译

-compiler , -printcompilation

  • Compiled:执行的编译任务数量。
  • Failed:编译任务失败的数量。
  • Invalid:被失效的编译任务数量。
  • Time:执行编译任务所花费的时间。
  • FailedType:最后一个失败编译任务的编译类型。
  • FailedMethod:最后一个失败编译任务的类名和方法名。

jmap+MAT实战内存溢出

如何导出内存映像文件

  • 内存溢出自动导出
    • -XX:+HeapDumpOnOutOfMemoryError, 启用内存溢出时自动导出
    • -XX:HeapDumpPath=./ , 指定导出文件的路径
  • 使用jmap命令手动导出
    • option: -heap, -clstats, -dump: , -F

基于jdk1.8的Java服务监控和性能调优_第11张图片

  • : 打印共享对象映射
  • -dump: 将Java堆内存以hprof二进制格式转储到文件中
  • -finalizerinfo: 打印等待终结的对象信息
  • -heap: 打印垃圾收集器使用情况、
  • -histo: 打印堆直方图,包括Java类的对象数量、内存大小和完全限定类名
  • -clstats: 打印每个类加载器的统计信息,包括名称、活动状态、地址、父类加载器以及已加载的类数和大小
  • -F: 强制模式,用于在pid不响应时使用-dump或-histo选项
  • -h或-help: 打印帮助信息
  • -J flag: 将flag传递给运行jmap命令的Java虚拟机
# dump出运行程序的堆状态, 以二进制文件格式保存到当前命令路径下的heap.hprof
jmap -dump:format=b,file=heap.hprof 48954

基于jdk1.8的Java服务监控和性能调优_第12张图片

双击文件直接在IDEA中就可以直接查看分析结果:

基于jdk1.8的Java服务监控和性能调优_第13张图片

分析内存溢出

测试触发内存溢出

测试com.imooc.monitor_tuning.chapter2.MemoryController#heap

idea程序启动运行参数:

-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./data

请求: http://localhost:8080/heap

使用mat分析内存对象

使用mat查看:提示可能内存溢出的是某个controller

基于jdk1.8的Java服务监控和性能调优_第14张图片

查看GC Roots, 排除弱引用,软引用等,只看强引用

基于jdk1.8的Java服务监控和性能调优_第15张图片

分析得知: Tomcat的thread引用了一个MemoryController, MemoryController引用了一个UserList, list里面是所有的User对象

使用mat查看对象占的字节数

使用IDEA自带的进行分析

基于jdk1.8的Java服务监控和性能调优_第16张图片

jstack实战死循环与死锁

一般CPU飙升很有可能就是死循环之类, 这时候就需要定位哪个线程出了问题

基本使用

基于jdk1.8的Java服务监控和性能调优_第17张图片

  • jstack [ options ] pid:打印指定进程 ID 的 Java 进程的堆栈跟踪信息。
  • jstack [ options ] executable core:打印从指定 Java 可执行文件生成的核心转储文件的堆栈跟踪信息。
  • jstack [ options ] [ server-id @ ] remote-hostname-or-IP:打印远程调试服务器主机名或 IP 地址上的 Java 进程的堆栈跟踪信息。
  • -F:当 jstack [ -l ] pid 没有响应时,强制进行堆栈转储。
  • -l:打印有关锁的其他信息,例如 java.util.concurrent 可拥有同步器的列表。有关 AbstractOwnableSynchronizer 类的说明,请参见 http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/AbstractOwnableSynchronizer.html 。
  • -m:打印混合模式堆栈跟踪,其中包含 Java 和本地 C/C++ 帧。

其中,pid 表示进程 ID,executable 表示 Java 可执行文件,core 表示核心转储文件,remote-hostname-or-IP 表示远程调试服务器主机名或 IP 地址,server-id 是可选的唯一 ID,用于在同一远程主机上运行多个调试服务器时进行区分。jps 命令可以用于获取在计算机上运行的 Java 进程列表,jsadebugd 命令可以用于启动远程调试服务器。

简单实用:

# 指定pid简单输出分析一下
jstack 61091 > data/61091.txt

基于jdk1.8的Java服务监控和性能调优_第18张图片

线程生命周期和状态:

具体可以参考: JAVA线程状态及状态间转换介绍 | 盖娅计划

基于jdk1.8的Java服务监控和性能调优_第19张图片

死循环分析

打包程序为jar包到远程服务器进行运行

基于jdk1.8的Java服务监控和性能调优_第20张图片

上传服务器:

# 需要改为你自己的服务器用户和ip地址
scp target/monitor_tuning-0.0.1-SNAPSHOT.jar [email protected]:/root/

登录服务器,然后启动服务:

java -jar monitor_tuning-0.0.1-SNAPSHOT.jar

基于jdk1.8的Java服务监控和性能调优_第21张图片

浏览器访问: http://172.16.237.144:8080/loop , 可以多开几个窗口访问

再开一个服务端的端口进行查看负载和进程:

基于jdk1.8的Java服务监控和性能调优_第22张图片

打印stack信息:

jstack 36850 > 36850.txt

查看对应的进程的线程信息:

# 用于查看进程 36850 的线程信息。具体来说,-p 选项指定要查看的进程 ID,-H 选项表示显示线程层次结构。
top -p 36850 -H

基于jdk1.8的Java服务监控和性能调优_第23张图片

由于Stack的信息是16进制,所以需要打印一下:

printf "%x" 36870

得到对应的16进制的线程id为9006, 然后打开前面的打印的栈信息进行查看,

这里可以下载下来用一些软件查看,不建议使用vim直接在线上环境打开 36850.txt,这里只是测试这样查看

vim 36850.txt
## /9006 即可找到

基于jdk1.8的Java服务监控和性能调优_第24张图片

定位到是com.imooc.monitor_tuning.chapter2.CpuController.getPartneridsFromJson 这个方法导致CPU升高, 最后检查代码进行修复

死锁分析

浏览器访问: http://172.16.237.144:8080/deadlock

基于jdk1.8的Java服务监控和性能调优_第25张图片

jps查看程序的java进程:

基于jdk1.8的Java服务监控和性能调优_第26张图片

同样适用jstack打印栈信息:

jstack 37143 > 37143.txt
vim 37143.txt

翻到文件末尾, 可以发现死锁的两个线程信息和对应的方法名

基于jdk1.8的Java服务监控和性能调优_第27张图片

你可能感兴趣的:(jvm,java,开发语言)