Java-第十四部分-JVM-调优概述和命令行工具

422 阅读7分钟

JVM全文

概述

  • 调优
  1. 防止出现OOM
  2. 解决OOM
  3. 减少Full GC出现的频率
  • 方向
  1. 合理编写代码
  2. 充分并合理地使用硬件资源
  3. 合理地进行JVM调优
  • 监控依据
  1. 运行日志
  2. 异常堆栈
  3. GC日志
  4. 线程快照
  5. 堆转储快照

性能优化的步骤

  • 性能监控,GC频繁;CPU load过高;OOM;内存泄漏;死锁;程序响应时间较长

非强行或入侵方式收集或查看性能数据的活动

  • 性能分析,打印GC日志、GCView分析日志信息;运用命令行工具、jstack、jmap、jinfo;dump出堆文件,内存分析工具;查看JVM状态
  1. 侵入的方式,主动收集运行性能数据的活动,影响吞吐量或响应性
  2. 通常在开发环境下进行
  • 性能调优,适当增加内存,根据业务背景选择垃圾回收器;优化代码,控制内存使用;增加机器,分散节点压力;合理设置线程池线程数量;使用中间件提高效率,如redis缓存、消息队列

为了改善应用响应性或吞吐量而更改参数、源代码、属性配置

性能评价、测试指标

  • 停顿时间、响应时间
  1. 提交请求和返回请求的响应之间使用的时间
  2. 暂停时间,垃圾回收过程中,程序的工作线程会被暂停 -XX:MaxGCPauseMillis
  • 吞吐量,单位时间内完成的工作量,TPS,单位时间处理用户的请求数
  1. 垃圾回收中,运行用户代码的时间占总运行时间的比例 -XX:GCTimeRation=n
  2. 1-1/(1+n)
  • 并发数,同一时刻,对服务器有实际交互的请求数
  • 内存占用,java堆区所占的内存大小
  • 举例,高速公路
  1. 吞吐量,每天通过高速公路收费站的车辆的数量(收费站收取的高速费)
  2. 并发数,高速公路正在行驶的车辆的数目
  3. 响应时间,车速
  4. 并发数增加 -> 响应时间下降 -> 吞吐量上升 -> 响应时间越来越慢 -> 吞吐量反而下降

调优命令行工具

jps

  • java process status,查询正在运行的虚拟机进程
  • ID与操作系统的进程ID一致
  • jps [options] [hostid]
  1. jps -q,只看到进程Id,优先显示,独立显示
  2. jps -l,全类名
  3. jps -m > jps.txt,查看运行时传递的相关参数 image.png
  4. jps -v,查看传递的JVM参数 image.png
  • -XX:-UsePerfData,关闭后,不能通过jps查看
  • <hostid>:      <hostname>[:<port>],远程查看,需要搭配jstated

jstat

  • JVM Statistics Monitoring Tool,查看JVM统计信息,监视虚拟机各种运行状态信息,类装载、内存、垃圾回收、JIT编译
  • jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

option

  • 类装载

-class 显示ClassLoader的相关信息,类装载、卸载数量、总空间、类装载所消耗的时间 image.png

  • JIT编译相关
  1. -compiler JIT编译器编译过的方法、耗时
  2. -printcompilation 输出已经被JIT编译的方法 image.png
  • 垃圾回收,通过OU参数,挑选多组最小的数据,如果最小值上升,老年代不能被回收的对象越来越多,存在内存泄漏问题
  1. -gc 显示于GC相关的堆信息,GCT为累加的时间 image.png
  2. -gccapacity 显示内容与上一个基本相同,主要关注java堆各个区域的最大、最小空间
  3. -gctuil 主要关注已使用空间占总空间的百分比 image.png
  4. -gccause 导致最后一次或当前正在发生的GC产生的原因;GCC正在发生GC的原因 image.png
  5. -gcnew 显示新生代GC状况
  6. -gcnewcapacity 主要关注使用到的最大、最小空间
  7. -geold 显示老年代GC状况
  8. -gcoldcapacity 主要关注使用到的最大、最小空间
  9. -gcpermcapacity 显示永久代使用的最大、最小空间

-t和-h

  • -t,程序开始执行到现在的时间,结合gc使用,可以计算出gc时间占运行时间的比例
  • jstat -class -t 85198 image.png
  • -h,在周期性数据输出时,输出表头数据
  • jstat -class -t -h3 85198 2000 10

每输出三条数据,重新打印表头 image.png

interval和count

  • interval,查询间隔,用于指定输出统计数据的周期,单位为毫秒
  • jstat -class 85198 2000
  • count,查询的总次数
  • jstat -class 85198 2000 10

查询id为85198的类装载情况,每隔2秒查询一次,共10次 image.png

jinfo

  • Configuration Info for Java
  • 查看虚拟机配置参数信息,调整虚拟机的配置参数
  • jinfo <option> <pid>

查看

  • -sysprops 查看系统参数
  • -flags 查看被赋过值的参数

jdk16 image.png jdk8 image.png

  • -flag查看执行参数 image.png

修改

  • 只能立即修改被标记为manageable的参数
  • java -XX:+PrintFlagsFinal -version | grep manageable 查看可以修改的 image.png
  • 修改,使用+/-修改,针对jdk8 image.png
  • 修改值类型 image.png

拓展

  • java -XX:+PrintFlagsInitial 查看所有JVM参数启动的初始值
  • java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值
  • java -XX:+PrintCommandLineFlags 查看已经被用户或者JVM设置过的详细的参数名称和值

jmap

  • JVM Memory Map
  • 导出内存映像文件以及内存使用情况
  • 获取dump文件(堆转储快照文件,保存堆情况),获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等
  • 为了保证此过程不被应用线程干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态,导出的dump文件必定是安全点位置,有所偏差

dump

  • JProfiler打开
  • java进程在某个时间点的内存快照,输出之前会触发一次full gc,保存的是gc后的内存映像信息,不能连续监测
  • 手动,根据实际情况选择
  1. jmap -dump:format=b,file=/Users/apple/Desktop/java/jvm/test.hprof 86785,format匹配格式
  2. jmap -dump:live,format=b,file=/Users/apple/Desktop/java/jvm/test1.hprof 86785,live只保存堆中的存活对象
  • 自动生成,发生OOM,自动导出dump文件

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/apple/Desktop/java/jvm/test2.hprof

显示堆内存信息

  • 当前时刻堆占用情况

jmap -heap 22635 > /home/server/current/a.txt

  • 内存空间详细对象情况

jmap -histo 22635 > /home/server/current/histo.txt image.png

  • jmap -finalizerinfo 22635 查看堆积在finalizer队列中的对象 image.png

jhat

  • JVM Heap Analysis Tool
  • 配合jmap的分析工作
  • jdk9之后被删除,下面演示linux
  • jhat test.hprof,端口7000,生成分析的界面的相关信息 image.png
  • -stack false|true 是否打开对象分配调用栈跟踪
  • -refs false|true 是否打开对象引用跟踪
  • -port port-number 设置端口
  • -exclude exclude-file 对象查询排除的数据成员
  • -baseline exclude-file 指定一个基准堆转储

jstack

  • JVM Stack Trace
  • 用于生成虚拟机指定线程当前时刻的线程快照,显示各个线程调用的堆栈情况
  • 线程状态,死锁、等待资源、等待获取同步监视器、阻塞、执行中、暂停、对象等待中、停止
  • jstack 92328 image.png
  • jstack -l 92328,锁信息 image.png
  • java代码追踪栈信息
Map<Thread, StackTraceElement[]> all = Thread.getAllStackTraces();
Set<Map.Entry<Thread, StackTraceElement[]>> entries = all.entrySet();
for (Map.Entry<Thread, StackTraceElement[]> entry : entries) {
    Thread key = entry.getKey();
    StackTraceElement[] value = entry.getValue();
    System.out.println("Tread name is :" + key.getName());
    for (StackTraceElement stackTraceElement : value) {
        System.out.println("\t" + stackTraceElement.toString());
    }
}

jcmd

  • 实现除了jstat之外的所有命令的功能
  • jcmd -l 列出所有进程,类似jps -m
  • jcmd 93061 help,指定进程支持的所有命令 image.png
  • jcmd 93061 Thread.print 打印线程信息,类似jstack
  • jcmd 93061 GC.class_histogram 内存对象详情,类似jmap -histo
  • jcmd 93061 GC.heap_dump /Users/apple/Desktop/java/jvm/d.hprof 生成dump文件
  • jcmd 93061 VM.uptime 执行的时间
  • jcmd 93061 VM.system_properties jvm系统属性

jstatd

  • 远程监控,相当于代理服务器,建立本地计算机与远程监控工具的通信