一切福田,不離方寸,從心而覓,感無不通。

JVM学习笔记

  • 大厂面试题
    • 支付宝
      • 支付宝三面:JVM性能调优都做了什么?

       

    • 小米
      • 有做过JVM内在优化吗?从SQL、JVM、架构、数据库4个方面讲讲优化思路

       

    • 蚂蚁金服
      • JVM的编译优化
      • JVM性能调优都做了什么?
      • JVM诊断调优工具用过哪些?
      • 二面:JVM怎样调优,堆内存、栈空间设置多少合适?
      • 三面:JVM相关的分析工具使用过哪些?具体的性能调优步骤如何?

       

    • 阿里
      • 如何进行JVM调优?有哪些方法?
      • 如何理解内存泄漏问题?有哪些情况会导致内存泄漏,如何解决?

       

    • 字节跳动
      • 三面:JVM如何调优,参数怎么调?

       

    • 拼多多
      • 从SQL、JVM、架构、数据库4个方面讲讲优化思路

       

    • 京东
      • JVM诊断调优工具用过哪些?
      • 每秒几十万并发的秒杀系统为什么会频繁发生GC?
      • 日均百万级交易系统如何优化JVM?
      • 线上生产系统OOM如何监控、定位 与解决?
      • 高并发系统如何基于G1垃圾回收器优化性能?

       

  • 为什么要调优?
    • 防止出现OOM
    • 解决OOM
    • 减少GC、Full GC出现频率

     

  • 监控的依据
    • 运行日志
    • 异常堆栈
    • GC日志
    • 线程快照
    • 堆转储快照

     

  • 性能调优的步骤?
    • 性能监控
      • 一种以非强行或入侵方式收集或查看应用运营性能数据的活动
      • 问题症状
        • GC频繁
        • CPU Load过高
        • OOM
        • 内存泄漏
        • 死锁
        • 响应时间较长
    • 性能分析
      • 一种以侵入方式收集运行性能数据的活动,它会影响应用的吞吐量或响应。
      • 方法
        • 打印GC日志,通过GCViewer或者http://gceasy.io来分析日志信息
        • 灵活运用命令行工具,jstack、jmap、jinfo等
        • dump出堆文件,使用内存分析工具分析
        • 使用阿里Arthas,或jconsole,JVisualVM来实时查看JVM状态
        • jstack查看堆栈信息
    • 性能调优
      • 适当增加内存,根据业务背景选择垃圾回收器
      • 优化代码,控制内存使用
      • 增加机器,分散节点压力
      • 合理设置线程池线程数量
      • 使用中间件提高程序效率,比如缓存,消息队列等

     

  • 性能指标
    • 停顿时间或响应时间
      • 打开一个站点:几秒
      • 数据库查询一条记录(有索引):十几毫秒
      • 机械磁盘一次寻址定位 :4毫秒
      • 从机械磁盘顺序读取1M数据:2毫秒
      • 从SSD顺序读取1M数据:0.3毫秒
      • 从Redis读取一条数据:0.5毫秒
      • 从内存读取1M数据:十几微秒
      • Java程序本地方法调用:几微秒
      • 网络传输2KB数据:1微秒
      • 启动参数:GC回收最大暂停时间 -XX:MaxGCPauseMillis
    • 吞吐量:单位时间内完成的工作量
      • 在GC中,运行用户代码的时间占总运行时间的比例(总运行时间=程序运行时间+内存回收时间)
      • 启动参数:-XX:GCTimeRatio=n,吞吐量为:1-1/(1+n)
    • 并发数:同一时刻,对服务器有实际交互的请求数
      • 计算方法:一般是在线人数的5% ~ 15%
    • 内存占用:Java堆区所占的内存大小
    • 相互间的关系
      以高速公路通行状况为例:

      • 吞吐量:每天通过高速公路收费站的车辆数据
      • 并发数:正在行驶的车辆的数量
      • 响应时间:车速

     

  • JVM监控及诊断工具:命令行篇
    使用数据说明问题,使用知识分析问题,使用工具处理问题

    • jps(Java Process Status):查看正在运行的Java进程
      • -q 仅显示id
      • -l 显示应用主类的全类名,如果是jar包则输入jar包的完整路径
      • -m 输出虚拟机进程传递给main()的参数
      • -v 列出虚拟机进程启动时的JVM参数
      • -XX:-UsePerfData可隐藏jps的探查
    • jstat(JVM Statistics Monitoring Tool):查看JVM统计信息
      jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

      • option参数
        • 类装载相关的
          • -class:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等
        • 垃圾回收相关的
          • -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。

            • 新生代相关
              • S0C 第一个幸存区的大小(byte)
              • S1C 第二个幸存区的大小(byte)
              • S0U 第一个幸存区已使用的大小(byte)
              • S1U 第二个幸存区已使用的大小(byte)
              • EC Eden空间的大小(byte)
              • EU Eden空间已使用大小(byte)
            • 老年代相关
              • OC 老年代大小(byte)
              • OU 老年代已使用大小(byte)
            • 方法区(元空间)相关
              • MC 方法区大小
              • MU 方法区已使用大小
              • CCSC 压缩类空间的大小
              • CCSU 压缩类已使用空间的大小
            • 其他
              • YGC 从应用程序启动到采样的young gc次数
              • YGCT 从应用程序启动到采样的young gc消耗的时间(秒)
              • FGC 从应用程序启动到采样的full gc次数
              • FGCT 从应用程序启动到采样的full gc消耗的时间(秒)
              • GCT 从应用程序启动到采样时的总时间(秒)
          • -gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
          • -gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
          • -gccause:与-gcutil功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。
          • -gcnew:显示新生代GC状况。
          • -gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用的最大、最小空间。
          • -gcold:显示老年代GC状况
        • JIT相关的
          • -compiler:显示JIT编译器编译过的方法、耗时等信息
          • -printcompilation:输出已经被 JIT编译的方法
      • interval参数:用于指定输出统计数据的周期,单位为毫秒。即查询间隔
      • count参数:用于指定查询的总次数
      • -t参数:可以在输出信息前加上一个Timestamp列,显示程序的运行时间,单位秒
      • -h参数:可以在周期性数据输出时,输出多少行数据后输出一个表头信息
    • jinfo(Configuration Info for Java):实时查看和修改JVM配置参数
      • jinfo -sysprops PID:可以查看由System.getProperties()获取的参数
      • jinfo -flags PID:查看曾经赋过值的一些参数
      • jinfo -flags 参数名 PID:查看某个进程的具体参数值
      • jinfo -flag [+|-] 参数名 PID:修改boolean类型参数
      • jinfo -flag 参数名=参数值 PID:修改非boolean类型参数
      • java -XX:+PrintFlagsFinal -version | grep manageable 查看可修改的参数
        • intx CMSAbortablePrecleanWaitMillis = 100
          intx CMSTriggerInterval = -1
          intx CMSWaitDuration = 2000
          bool HeapDumpAfterFullGC = false
          bool HeapDumpBeforeFullGC = false
          bool HeapDumpOnOutOfMemoryError = false
          ccstr HeapDumpPath =
          uintx MaxHeapFreeRatio = 100
          uintx MinHeapFreeRatio = 0
          bool PrintClassHistogram = false
          bool PrintClassHistogramAfterFullGC = false
          bool PrintClassHistogramBeforeFullGC = false
          bool PrintConcurrentLocks = false
          bool PrintGC = false
          bool PrintGCDateStamps = false
          bool PrintGCDetails = false
          bool PrintGCID = false
          bool PrintGCTimeStamps = false
          uintx ShenandoahSoftMaxHeapSize = 0
      • java -XX:+PrintFlagsInitial:查看所有JVM参数启动的初始值
      • java -XX:+PrintFlagsFinal:查看所有JVM参数的最终值
      • java -XX:+PrintCommandLineFlags:查看那些已经被用户或JVM设置过的详细的XX参数的名称和值
    • jmap(JVM Memory Map):导出内存映像文件&内存使用情况
      • -dump 生成java堆转储快照:dump文件;特别的:-dump:live只保存堆中的存活对象
        jmap -dump:format=b,file=<filename.hprof> <pid>
        jmap -dump:live,format=b,file=<filename.hprof> <pid>
        -XX:+HeapDumpOnOutOfMemoryError
        -XX:HeapDumpPath=<filename.hprof>
      • -heap 输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
      • -histo 输出堆中对象的统计信息,包括类、实例数量和合计容量;特别的:-histo:live只统计堆中的存活对象
      • -permstat 以ClassLoader为统计口径输出永久的内存状态信息,仅linux/solaris平台有效
      • -finallizerinfo 显示在F-Queue中等待Finalizer线程执行的finalize方法的对象,仅linux/solaris平台有效
      • -F 当虚拟机进程对-dump选项没有任何响应时,可以使用此选项强制生成dump文件,仅linux/solaris平台有效
      • -h | -help jmap工具使用的帮助命令
      • -J <flag> 传递参数给jmap启动的jvm
    • jhat(JVM Heap Analysis Tool):JDK自带堆分析工具,用于分析jmap生成的heap dump文件。jhat内置了一个微型的http/html服务器,生成dump文件的分析结果后,用户可以在浏览器查看分析结果。使用jhat命令,就启动了一个http服务,端口是7000。jhat命令在JDK9、JDK10中已经被删除,官方建议用VisualVM代替。
    • jstack(JVM Stack Trace):打印JVM中线程快照,用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。
      • 在thread dump中,要留意下面几种状态:
        死锁,Deadlock
        等待资源,Waiting on condition
        等待获取监视器,Waiting on monitor entry
        阻塞,Blocked
        执行中,Runnable
        暂停,Suspended
        对象等待中,Object.wait() 或 TIME_WAITING
        停止,Parked
      • option参数
        • -F 当正常输出的请求不被响应时,强制输出线程堆栈
        • -l 除堆栈外,显示关于锁的附加信息
        • -m 如果调用到本地方法的话,可以显示C/C++的堆栈
        • -h 帮助操作
    • jcmd:多功能命令行
    • jstatd:远程主机信息收集