性能与调优

一. JDK 命令行工具

1. 内存分配和回收 - GC 日志解读

  1. 1. 默认 JVM 不会打印出 GC 日志信息,可以通过参数来设置 JVM 输出 GC 日志到终端中
  2. JVM 参数:
  3. -Dcom.sun.management.jmxremote=true JMX 管理功能, 部分 JVM 工具是基于 JMX 的, 所以要开启此选项)
  4. -XX:+PrintGCTimeStamps(打印GC停顿时间)
  5. -XX:+PrintGCDetails(打印GC详细信息)
  6. -verbose:gc(打印GC信息,输出内容已被前一个参数包括,可以不写)、-Xloggc:gc.log
  7. 2. GC 日志案例
  8. 33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K->152K(11904K), 0.0031680 secs]
  9. 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]
  10. 3. GC 日志规则
  11. 33.125100.667
  12. 表示 GC 发生时间, JVM 虚拟机启动后, 发生 GC 的秒数
  13. [GC、[Full GC
  14. 表示 GC 的停顿类型, 如果有 Full GC 表示发生了 Stop The World, 如果是通过调用 System.gc() 则会显示成 [Full GC(System)
  15. [DefNew、[Tenured、[Perm
  16. 表示 GC 发生的区域
  17. DefNew: 表示使用新生代收集器 Serial
  18. ParNew: 表示使用新生代收集器 ParNew
  19. PSYoungGen: 表示使用新生代收集器 Parallel Scavenge
  20. 年老代同理
  21. [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K->152K(11904K), 0.0031680 secs
  22. 表示 GC 区域、GC 堆的容量和耗时信息
  23. 方括号 [] 之内, 表示区域 DefNew 的内存回收情况
  24. 方括号 [] 之外, 表示堆的内存回收情况
  25. [DefNew: 3324K -> 152K (3712K) , 0.0025925 secs] 3324K -> 152K (11904K), 0.0031680 secs
  26. [DefNew: GC 前内存区域容量 -> GC 后的区域容量 (区域总容量), GC 耗时秒数 GC 前堆容量 -> GC 后堆容量 (堆总容量) GC 总耗时秒数
  27. [Times: user=0.01 sys=0.00, real=0.02 secs]
  28. 表示 GC 的详细时间, Linux time 命令含义一致
  29. user: 用户态消耗的 CPU 时间, 当系统有多个 CPU 或者多核, 多线程操作会叠加这些 CPU 时间, 所以 user 或者 sys 超过 real 时间很正常
  30. sys: 内核态消耗的 CPU 事件
  31. real: 操作从开始到结束所经过的樯钟时间(Wall Clock Time), CPU 时间的区别是: 樯钟时间包括各种非运算的等待耗时(等待磁盘 I/O、等待线程阻塞), CPU 时间则不包含这些

二. JDK 命令行工具

1. jps

  • 虚拟机进程状况工具, 显示所有 HotSpot 虚拟机运行的进程
  1. jps [ option ] [ hostid ]
  2. jps -l 显示主类全名和路径
  3. jps -v 显示虚拟机进程启动时, 传递给 JVM 参数
  4. jps -m 显示虚拟机进程启动时, 传递给主类 main() 函数的参数
  5. jps -q 只显示 LVMID

2. jstat

  • 虚拟机统计信息监控工具, 收集 HotSpot 虚拟机各方面的运行参数
  • 显示本地或者远程虚拟机进程中的类装在、内存、垃圾收集、JIT 编译等运行数据
  1. jstat [ option vmid [ interval[s|ms] [count] ] ]
  2. vmid : VMID 格式: 进程 ID
  3. LVMID 格式: [protocol:][//]lvmid[@hostname[:port]/servername]
  4. interval: 查询间隔
  5. count: 查询次数
  6. jstat -gc [vmid] 1s 5
  7. 监控 Java 堆状况, 包括 Eden 区域、survivor 两个、老年代、永久代等的容量、已用时间、GC 时间合计等信息
  8. jstat -gccapacity [vmid]
  9. -gc, 但主要显示 Java 堆各个区域使用到的最大、最小空间
  10. jstat -gcutil [vmid]
  11. -gc, 但主要显示已使用空间占总空间的百分比
  12. jstat -gccause [vmid]
  13. -gcutil, 但是会显示上一次 GC 产生的原因
  14. jstat -gcnew [vmid]
  15. 监控新生代 GC
  16. jstat -gcnewcapacity [vmid]
  17. -gcnew, 但主要显示区域使用到的最大、最小空间
  18. jstat -gcold [vmid]
  19. 显示老年代 GC 信息
  20. jstat -gcoldcapacity [vmid]
  21. -gcold, 但主要显示区域使用到的最大、最小空间
  22. jstat -gcpermcapacity [vmid]
  23. 显示永久代区域使用到的最大、最小空间
  24. 日志字段解读:
  25. 1) -gccause 堆比例显示的参数
  26. S0 (Survivor0 使用百分比)
  27. S1 (Survivor1 使用百分比)
  28. E (Eden 使用百分比)
  29. O (Old 使用百分比)
  30. P (Permanent 永久代使用百分比)
  31. YGC (Young GC Minor GC 总次数)
  32. YGCT (YGC 总耗时秒)
  33. FGC (Full GC 总次数)
  34. FGCT (Full GC 总耗时秒)
  35. GCT (所有 GC 耗时)
  36. GCC (上一次 GC 原因)
  37. 2) -gcpermcapacity 永久代显示的大小参数
  38. PGCMN 最小永久代
  39. PGCMX 最大永久代
  40. PGC
  41. PC
  42. YGC
  43. FGC
  44. FGCT
  45. GCT
  46. 3) -gcnewcapacity 新生代显示的大小参数
  47. NGCMN 最小新生代
  48. NGCMX 最大新生代
  49. NGC
  50. S0CMX
  51. S0C
  52. S1CMX
  53. S1C
  54. ECMX
  55. EC
  56. YGC
  57. FGC
  58. 4) -gcoldcapacity 老年代显示的大小参数
  59. OGCMN
  60. OGCMX
  61. OGC
  62. OC
  63. YGC
  64. FGC
  65. FGCT
  66. GCT

3. jinfo

  • Java 配置信息工具, 显示虚拟机配置信息
  • 动态修改虚拟机的配置
  1. jinfo [ option ] pid
  2. jinfo -sysprops [pid]
  3. 显示运行时参数
  4. jinfo -flag[+|-] | -flag name=value
  5. 修改部分运行期间可写的参数
  6. 例如: jinfo -flag CMSInitiatingOccupancyFraction [pid]
  7. jinfo -flag MaxGCPauseMillis [pid]

4. jmap

  • Java 内存印像工具, 生成虚拟机的内存转储快照(heapdump) 文件
  • 查询 finalize 执行队列、Java 堆和永久代信息, 空间使用率、当前使用的 GC 回收期等信息
  1. -XX:+HeapDumpOnOutOfMemoryError
  2. 如果不使用 jmap 工具, 可通过开启此选项在 JVM OOM 异常后生成 heapdump 文件
  3. -XX:+HeapDumpOnCtrlBreak
  4. 使用快捷键 [Ctrl]+[Break] 让虚拟机生成 heapdump 文件
  5. jmap [option] vmid
  6. jamp -heap vmid
  7. kill -3 命令发送退出信号, 提醒 JVM 一下, 也能拿到 heapdump 文件

5. jhat

  • 虚拟机堆转储快照分析工具, 用于分析 heapdump 文件, 会建立一个 HTTP/HTML 服务器, 可以在浏览器查看分析结果

6. jstack

  • Java 堆栈跟踪工具, 显示虚拟机的线程快照

7. HSDIS

  • JIT 生成代码反汇编

二. JDK 可视化工具

可视化工具参数

  1. ## JMX 管理功能, 部分 JVM 工具是基于 JMX 的, 所以要开启此选项
  2. -Dcom.sun.management.jmxremote=true
  3. ## 指定了JMX启动的代理端口,这个端口就是visualvm要连接的端口(9998端口不能被别的程序使用netstat -an|gerp 9998)
  4. -Dcom.sun.management.jmxremote.port=[port]
  5. # 指定了JMX是否启用ssl
  6. -Dcom.sun.management.jmxremote.authenticate=false
  7. # 指定了JMX是否启用鉴权(需要用户名,密码鉴权)
  8. -Dcom.sun.management.jmxremote.authenticate=false
  9. # 指定服务器主机名
  10. -Djava.rmi.server.hostname=appNtest

1. JConsole

  • Java 监视与管理控制台
  1. # 1. Java 启动时, 增加如下参数, 程序会开启 TCP 端口 9100, 使用 JConsole 连接即可. (具体 Java 程序根据情况定义, 这里是一个案例)
  2. java -Dcom.sun.management.jmxremote=true \
  3. -Dcom.sun.management.jmxremote.port=9100 \
  4. -Dcom.sun.management.jmxremote.authenticate=false \
  5. -Dcom.sun.management.jmxremote.ssl=false \
  6. -Dfile.encoding=UTF-8 \
  7. -jar ~/app/dw_general_loader/run/dw_general_loader.jar dim_product_kpi 2018-02-27
  8. # 2. Java 客户端工具, 用于界面显示 Java 程序运行是的变化
  9. ## 命令行方式启动
  10. $JAVA_HOME/bin/jconsole ip:port
  11. ## 启动界面, 输入远程连接即可
  12. $JAVA_HOME/bin/jconsole
  13. # 3. PS 注意一点, 如果提示需要密码文件, 需要给与 chmod 600 权限
  14. chmod 600 $JAVA_HOME/jre/lib/management/jmxremote.password

2. VisualVM

  • Java 多合一故障处理工具
  1. # 1. 程序启动监控
  2. java -Dcom.sun.management.jmxremote=true \
  3. -Dcom.sun.management.jmxremote.port=9200 \
  4. -Dcom.sun.management.jmxremote.ssl=false \
  5. -Dcom.sun.management.jmxremote.authenticate=false \
  6. -Dfile.encoding=UTF-8 \
  7. -jar ~/app/dw_general_loader/run/dw_general_loader.jar dim_product_kpi 2018-02-27
  8. # 2. Java 客户端工具, 用于界面显示 Java 程序运行是的变化
  9. $JAVA_HOME/bin/jvisualvm

3. jstatd

  • 使用 jstatd 监控目标主机上的所有 jvm 进程
  1. # 1. 配置策略文件
  2. ## 创建策略目录
  3. mkdir -p $JAVA_HOME/policy
  4. ## 编辑策略文件 jstatd.all.policy, 写入如下信息
  5. vim $JAVA_HOME/policy/jstatd.all.policy
  6. grant codebase "file:${java.home}/../lib/tools.jar" {
  7. permission java.security.AllPermission;
  8. };
  9. # 2. 启动 jstatd 守护进程
  10. $JAVA_HOME/bin/jstatd -J-Djava.security.policy=$JAVA_HOME/policy/jstatd.all.policy -p 9300
  11. # 3. 连接器使用 VisualVM
  12. $JAVA_HOME/bin/jvisualvm

4. 插件

由于插件迁移到了 github, 新地址 可用插件的地址, 根据 JDK 版本选择插件版本

  • Visual GC

  • BTrace