性能与调优
一. JDK 命令行工具
1. 内存分配和回收 - GC 日志解读
1. 默认 JVM 不会打印出 GC 日志信息,可以通过参数来设置 JVM 输出 GC 日志到终端中JVM 参数:-Dcom.sun.management.jmxremote=true (JMX 管理功能, 部分 JVM 工具是基于 JMX 的, 所以要开启此选项)-XX:+PrintGCTimeStamps(打印GC停顿时间)-XX:+PrintGCDetails(打印GC详细信息)-verbose:gc(打印GC信息,输出内容已被前一个参数包括,可以不写)、-Xloggc:gc.log2. GC 日志案例33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K->152K(11904K), 0.0031680 secs]100.667: [Full GC [Tenured: OK->210K(10240K), 0.0149142 secs] 4603K->210K(19456K), [Perm : 2999K->2999K(21248K)], 0.015007 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]3. GC 日志规则33.125、100.667表示 GC 发生时间, 从 JVM 虚拟机启动后, 发生 GC 的秒数[GC、[Full GC表示 GC 的停顿类型, 如果有 Full GC 表示发生了 Stop The World, 如果是通过调用 System.gc() 则会显示成 [Full GC(System)[DefNew、[Tenured、[Perm表示 GC 发生的区域DefNew: 表示使用新生代收集器 SerialParNew: 表示使用新生代收集器 ParNewPSYoungGen: 表示使用新生代收集器 Parallel Scavenge年老代同理[DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K->152K(11904K), 0.0031680 secs表示 GC 区域、GC 堆的容量和耗时信息方括号 [] 之内, 表示区域 DefNew 的内存回收情况方括号 [] 之外, 表示堆的内存回收情况[DefNew: 3324K -> 152K (3712K) , 0.0025925 secs] 3324K -> 152K (11904K), 0.0031680 secs[DefNew: GC 前内存区域容量 -> GC 后的区域容量 (区域总容量), GC 耗时秒数 GC 前堆容量 -> GC 后堆容量 (堆总容量) GC 总耗时秒数[Times: user=0.01 sys=0.00, real=0.02 secs]表示 GC 的详细时间, 与 Linux 的 time 命令含义一致user: 用户态消耗的 CPU 时间, 当系统有多个 CPU 或者多核, 多线程操作会叠加这些 CPU 时间, 所以 user 或者 sys 超过 real 时间很正常sys: 内核态消耗的 CPU 事件real: 操作从开始到结束所经过的樯钟时间(Wall Clock Time), 与 CPU 时间的区别是: 樯钟时间包括各种非运算的等待耗时(等待磁盘 I/O、等待线程阻塞), CPU 时间则不包含这些
二. JDK 命令行工具
1. jps
- 虚拟机进程状况工具, 显示所有 HotSpot 虚拟机运行的进程
jps [ option ] [ hostid ]jps -l 显示主类全名和路径jps -v 显示虚拟机进程启动时, 传递给 JVM 参数jps -m 显示虚拟机进程启动时, 传递给主类 main() 函数的参数jps -q 只显示 LVMID
2. jstat
- 虚拟机统计信息监控工具, 收集 HotSpot 虚拟机各方面的运行参数
- 显示本地或者远程虚拟机进程中的类装在、内存、垃圾收集、JIT 编译等运行数据
jstat [ option vmid [ interval[s|ms] [count] ] ]vmid : VMID 格式: 进程 IDLVMID 格式: [protocol:][//]lvmid[@hostname[:port]/servername]interval: 查询间隔count: 查询次数jstat -gc [vmid] 1s 5监控 Java 堆状况, 包括 Eden 区域、survivor 两个、老年代、永久代等的容量、已用时间、GC 时间合计等信息jstat -gccapacity [vmid]同 -gc, 但主要显示 Java 堆各个区域使用到的最大、最小空间jstat -gcutil [vmid]同 -gc, 但主要显示已使用空间占总空间的百分比jstat -gccause [vmid]同 -gcutil, 但是会显示上一次 GC 产生的原因jstat -gcnew [vmid]监控新生代 GCjstat -gcnewcapacity [vmid]同 -gcnew, 但主要显示区域使用到的最大、最小空间jstat -gcold [vmid]显示老年代 GC 信息jstat -gcoldcapacity [vmid]同 -gcold, 但主要显示区域使用到的最大、最小空间jstat -gcpermcapacity [vmid]显示永久代区域使用到的最大、最小空间日志字段解读:1) -gccause 堆比例显示的参数S0 (Survivor0 使用百分比)S1 (Survivor1 使用百分比)E (Eden 使用百分比)O (Old 使用百分比)P (Permanent 永久代使用百分比)YGC (Young GC 或 Minor GC 总次数)YGCT (YGC 总耗时秒)FGC (Full GC 总次数)FGCT (Full GC 总耗时秒)GCT (所有 GC 耗时)GCC (上一次 GC 原因)2) -gcpermcapacity 永久代显示的大小参数PGCMN 最小永久代PGCMX 最大永久代PGCPCYGCFGCFGCTGCT3) -gcnewcapacity 新生代显示的大小参数NGCMN 最小新生代NGCMX 最大新生代NGCS0CMXS0CS1CMXS1CECMXECYGCFGC4) -gcoldcapacity 老年代显示的大小参数OGCMNOGCMXOGCOCYGCFGCFGCTGCT
3. jinfo
- Java 配置信息工具, 显示虚拟机配置信息
- 动态修改虚拟机的配置
jinfo [ option ] pidjinfo -sysprops [pid]显示运行时参数jinfo -flag[+|-] | -flag name=value修改部分运行期间可写的参数例如: jinfo -flag CMSInitiatingOccupancyFraction [pid]jinfo -flag MaxGCPauseMillis [pid]
4. jmap
- Java 内存印像工具, 生成虚拟机的内存转储快照(heapdump) 文件
- 查询 finalize 执行队列、Java 堆和永久代信息, 空间使用率、当前使用的 GC 回收期等信息
-XX:+HeapDumpOnOutOfMemoryError如果不使用 jmap 工具, 可通过开启此选项在 JVM OOM 异常后生成 heapdump 文件-XX:+HeapDumpOnCtrlBreak使用快捷键 [Ctrl]+[Break] 让虚拟机生成 heapdump 文件jmap [option] vmidjamp -heap vmidkill -3 命令发送退出信号, 提醒 JVM 一下, 也能拿到 heapdump 文件
5. jhat
- 虚拟机堆转储快照分析工具, 用于分析 heapdump 文件, 会建立一个 HTTP/HTML 服务器, 可以在浏览器查看分析结果
6. jstack
- Java 堆栈跟踪工具, 显示虚拟机的线程快照
7. HSDIS
- JIT 生成代码反汇编
二. JDK 可视化工具
可视化工具参数
## JMX 管理功能, 部分 JVM 工具是基于 JMX 的, 所以要开启此选项-Dcom.sun.management.jmxremote=true## 指定了JMX启动的代理端口,这个端口就是visualvm要连接的端口(9998端口不能被别的程序使用netstat -an|gerp 9998)-Dcom.sun.management.jmxremote.port=[port]# 指定了JMX是否启用ssl-Dcom.sun.management.jmxremote.authenticate=false# 指定了JMX是否启用鉴权(需要用户名,密码鉴权)-Dcom.sun.management.jmxremote.authenticate=false# 指定服务器主机名-Djava.rmi.server.hostname=appNtest
1. JConsole
- Java 监视与管理控制台
# 1. Java 启动时, 增加如下参数, 程序会开启 TCP 端口 9100, 使用 JConsole 连接即可. (具体 Java 程序根据情况定义, 这里是一个案例)java -Dcom.sun.management.jmxremote=true \-Dcom.sun.management.jmxremote.port=9100 \-Dcom.sun.management.jmxremote.authenticate=false \-Dcom.sun.management.jmxremote.ssl=false \-Dfile.encoding=UTF-8 \-jar ~/app/dw_general_loader/run/dw_general_loader.jar dim_product_kpi 2018-02-27# 2. Java 客户端工具, 用于界面显示 Java 程序运行是的变化## 命令行方式启动$JAVA_HOME/bin/jconsole ip:port## 启动界面, 输入远程连接即可$JAVA_HOME/bin/jconsole# 3. PS 注意一点, 如果提示需要密码文件, 需要给与 chmod 600 权限chmod 600 $JAVA_HOME/jre/lib/management/jmxremote.password
2. VisualVM
- Java 多合一故障处理工具
# 1. 程序启动监控java -Dcom.sun.management.jmxremote=true \-Dcom.sun.management.jmxremote.port=9200 \-Dcom.sun.management.jmxremote.ssl=false \-Dcom.sun.management.jmxremote.authenticate=false \-Dfile.encoding=UTF-8 \-jar ~/app/dw_general_loader/run/dw_general_loader.jar dim_product_kpi 2018-02-27# 2. Java 客户端工具, 用于界面显示 Java 程序运行是的变化$JAVA_HOME/bin/jvisualvm
3. jstatd
- 使用 jstatd 监控目标主机上的所有 jvm 进程
# 1. 配置策略文件## 创建策略目录mkdir -p $JAVA_HOME/policy## 编辑策略文件 jstatd.all.policy, 写入如下信息vim $JAVA_HOME/policy/jstatd.all.policygrant codebase "file:${java.home}/../lib/tools.jar" {permission java.security.AllPermission;};# 2. 启动 jstatd 守护进程$JAVA_HOME/bin/jstatd -J-Djava.security.policy=$JAVA_HOME/policy/jstatd.all.policy -p 9300# 3. 连接器使用 VisualVM$JAVA_HOME/bin/jvisualvm
4. 插件
由于插件迁移到了 github, 新地址 可用插件的地址, 根据 JDK 版本选择插件版本
Visual GC
BTrace
