JVM性能调优基础

目录

一、概述

什么时候需要调优

调优目标

调优原则

调优指标

二、调优步骤

触发full gc场景和对应策略

三、最佳实践参数

四、调优工具

jdk原生工具

jps虚拟机进程状况工具

jstat:虚拟机统计信息监视工具

jinfo:Java配置信息工具

jmap:Java内存映像工具

jhat:虚拟机堆转储快照分析工具

jstack:Java堆栈跟踪工具

可视化工具分析

GCview

JVisualVM


一、概述

什么时候需要调优

1. heap 内存(老年代)持续上涨达到设置的最大内存值;
2. Full GC 次数频繁;
3. GC 停顿时间过长(超过1秒);
4. 应用出现OutOfMemory 等内存异常;
5. 系统cpu、内存等性能指标过高或响应时间过长。

调优目标

1. 低延迟(GC低停顿、 GC低频率)
2. 低内存占用; 
3. 高吞吐量;

调优原则

大多数应用不要JVM调优,多数gc问题都是问题代码导致的。优先架构调优和代码调优最后考虑jvm参数调优。

调优指标

1. 内存使用率 <= 70%;
2. 老年代内存使用率<= 70%;
3. 响应时间小于等于1秒; 
4. Full gc 次数0 或 avg pause interval >= 24小时 ;
注意:不同应用,其JVM调优量化目标是不一样的。

二、调优步骤

      第1步:分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点;
      第2步:确定JVM调优量化目标;
      第3步:确定JVM调优参数(根据历史JVM参数来调整);
      第4步:调优一台服务器,对比观察调优前后的差异;
      第5步:不断的分析和调整,直到找到合适的JVM参数配置;
      第6步:找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。

触发full gc场景和对应策略

年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为MajorGC,而Full GC是对整个堆来说的。出现Full GC的时候经常伴随至少一次的Minor GC,但非绝对的。MajorGC的速度一般会比Minor GC慢10倍以上。

1、禁用System.gc(),通过-XX:+DisableExplicitGC来禁止调用System.gc

2、老年代空间不足,让对象在Minor GC阶段被回收,尽量不创建大对象。

3、元空间不足,增大PermGen空间

4、GC时出现promotionfailed和concurrent mode failure,应对策略:增大survivor space

5、Minor GC后晋升到旧生代的对象大小大于老年代的剩余空间,应对策略:增大Tenured space 或下调CMSInitiatingOccupancyFraction=60

6、内存持续增涨达到上限导致Full GC ,应对策略:通过dumpheap 分析是否存在内存泄漏

三、最佳实践参数

4c8g服务器一般通用最佳配置:

-Xms4g \
-Xmx4g \
-Xmn3g \
-XX:MetaspaceSize=256m \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/usr/local/oom \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-XX:+PrintTenuringDistribution \
-Xloggc:logs/gc.log \
-Xms4g \ 初始化堆大小
-Xmx4g \ 堆内存最大值(初始值和最大值设置相同,避免GC后调整堆大小带来的压力)
-Xmn3g \ 新生代大小包括Eden区与2个Survivor区
-XX:MetaspaceSize=256m \ 元空间大小
-XX:MaxMetaspaceSize=256m \ 元空间最大可分配大小 。(1、如果不指定元空间的大小,默认情况下,元空间最大的大小是系统内存的大小,元空间一直扩大,虚拟机可能会消耗完所有的可用系统内存。2、如果元空间内存不够用,就会报OOM。3.默认情况下,对应一个64位的服务端JVM来说,其默认的-XX:MetaspaceSize值为21MB,这就是初始的高水位线,一旦元空间的大小触及这个高水位线,就会触发Full GC并会卸载没有用的类,然后高水位线的值将会被重置。4、为了避免频繁GC以及调整高水位线,建议将-XX:MetaspaceSize设置为较高的值,而-XX:MaxMetaspaceSize不进行设置。)
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/usr/local/oom \  参数表示当JVM发生OOM时,自动生成DUMP文件

导出dump堆转储快照文件

当程序发生OOM时,一些瞬时信息都随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时。此时若能在OOM时,自动导出dump文件就显得非常迫切。

-XX:+HeapDumpOnOutOfMemoryError:在程序发生OOM时,导出应用程序的当前堆快照。
-XX:HeapDumpPath:可以指定堆快照的保存位置

gc日志配置

-XX:+PrintGC #输出GC日志
-XX:+PrintGCDetails #输出GC的详细日志
-XX:+PrintGCTimeStamps #输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps #输出GC的时间戳(以日期的形式,如 2017-09-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC #在进行GC的前后打印出堆的信息
-Xloggc:gc.log #日志文件的输出路径

其他重要参数:

-Xms12g:初始化堆内存大小为12GB。
-Xmx12g:堆内存最大值为12GB 。
-Xmn2400m:新生代大小为2400MB,包括 Eden区与2个Survivor区。
-XX:SurvivorRatio=1:Eden区与一个Survivor区比值为1:1。
-XX:MaxDirectMemorySize=1G:直接内存。报java.lang.OutOfMemoryError: Direct buffer memory 异常可以上调这个值。
-XX:+DisableExplicitGC:禁止运行期显式地调用 System.gc() 来触发fulll GC。
注意: Java RMI的定时GC触发机制可通过配置-Dsun.rmi.dgc.server.gcInterval=86400来控制触发的时间。
-XX:CMSInitiatingOccupancyFraction=60:老年代内存回收阈值,默认值为68。
-XX:ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。
-XX:ParallelGCThreads=8:新生代并行收集器的线程数。
-XX:MaxTenuringThreshold=10:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
-XX:CMSFullGCsBeforeCompaction=4:指定进行多少次fullGC之后,进行tenured区 内存空间压缩。
-XX:CMSMaxAbortablePrecleanTime=500:当abortable-preclean预清理阶段执行达到这个时间时就会结束。

四、调优工具

  • jdk原生工具

jps虚拟机进程状况工具

命令格式

jps [options] [hostid]

option参数:

  • -l : 输出主类全名或jar路径

  • -q : 只输出LVMID

  • -m : 输出JVM启动时传递给main()的参数

  • -v : 输出JVM启动时显示指定的JVM参数

jstat:虚拟机统计信息监视工具

用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

命令格式

jstat [option] LVMID [interval] [count]

参数

  • [option] : 操作参数

  • LVMID : 本地虚拟机进程ID

  • [interval] : 连续输出的时间间隔

  • [count] : 连续输出的次数

option 参数总览

Option Displays…
class class loader的行为统计。Statistics on the behavior of the class loader.
compiler HotSpt JIT编译器行为统计。Statistics of the behavior of the HotSpot Just-in-Time compiler.
gc 垃圾回收堆的行为统计。Statistics of the behavior of the garbage collected heap.
gccapacity 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计。Statistics of the capacities of the generations and their corresponding spaces.
gcutil 垃圾回收统计概述。Summary of garbage collection statistics.
gccause 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因。Summary of garbage collection statistics (same as -gcutil), with the cause of the last and
gcnew 新生代行为统计。Statistics of the behavior of the new generation.
gcnewcapacity 新生代与其相应的内存空间的统计。Statistics of the sizes of the new generations and its corresponding spaces.
gcold 年老代和永生代行为统计。Statistics of the behavior of the old and permanent generations.
gcoldcapacity 年老代行为统计。Statistics of the sizes of the old generation.
gcpermcapacity 永生代行为统计。Statistics of the sizes of the permanent generation.
printcompilation HotSpot编译方法统计。HotSpot compilation method statistics.

option 参数详解

-class

监视类装载、卸载数量、总空间以及耗费的时间

$ jstat -class 11589
  • Loaded : 加载class的数量

  • Bytes : class字节大小

  • Unloaded : 未加载class的数量

  • Bytes : 未加载class的字节大小

  • Time : 加载时间

-compiler

输出JIT编译过的方法数量耗时等

$ jstat -compiler 1262
  • Compiled : 编译数量

  • Failed : 编译失败数量

  • Invalid : 无效数量

  • Time : 编译耗时

  • FailedType : 失败类型

  • FailedMethod : 失败方法的全限定名

-gc

垃圾回收堆的行为统计,常用命令

$ jstat -gc 1262

C即Capacity 总容量,U即Used 已使用的容量

  • S0C : survivor0区的总容量

  • S1C : survivor1区的总容量

  • S0U : survivor0区已使用的容量

  • S1C : survivor1区已使用的容量

  • EC : Eden区的总容量

  • EU : Eden区已使用的容量

  • OC : Old区的总容量

  • OU : Old区已使用的容量

  • PC 当前perm的容量 (KB)

  • PU perm的使用 (KB)

  • YGC : 新生代垃圾回收次数

  • YGCT : 新生代垃圾回收时间

  • FGC : 老年代垃圾回收次数

  • FGCT : 老年代垃圾回收时间

  • GCT : 垃圾回收总消耗时间

$ jstat -gc 1262 2000 20

这个命令意思就是每隔2000ms输出1262的gc情况,一共输出20次

-gccapacity

同-gc,不过还会输出Java堆各区域使用到的最大、最小空间

$ jstat -gccapacity 1262
  • NGCMN : 新生代占用的最小空间

  • NGCMX : 新生代占用的最大空间

  • OGCMN : 老年代占用的最小空间

  • OGCMX : 老年代占用的最大空间

  • OGC:当前年老代的容量 (KB)

  • OC:当前年老代的空间 (KB)

  • PGCMN : perm占用的最小空间

  • PGCMX : perm占用的最大空间

-gcutil

同-gc,不过输出的是已使用空间占总空间的百分比

$ jstat -gcutil 28920

-gccause

垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因

$ jstat -gccause 28920
  • LGCC:最近垃圾回收的原因

  • GCC:当前垃圾回收的原因

-gcnew

统计新生代的行为

$ jstat -gcnew 28920
  • TT:Tenuring threshold(提升阈值)

  • MTT:最大的tenuring threshold

  • DSS:survivor区域大小 (KB)

-gcnewcapacity

新生代与其相应的内存空间的统计

$ jstat -gcnewcapacity 28920NGC:当前年轻代的容量 (KB)
  • S0CMX:最大的S0空间 (KB)

  • S0C:当前S0空间 (KB)

  • ECMX:最大eden空间 (KB)

  • EC:当前eden空间 (KB)

-gcold

统计旧生代的行为

$ jstat -gcold 28920

-gcoldcapacity

统计旧生代的大小和空间

$ jstat -gcoldcapacity 28920

-gcpermcapacity

永生代行为统计

$ jstat -gcpermcapacity 28920

printcompilation

hotspot编译方法统计

$ jstat -printcompilation 28920
  • Compiled:被执行的编译任务的数量

  • Size:方法字节码的字节数

  • Type:编译类型

  • Method:编译方法的类名和方法名。类名使用"/" 代替 "." 作为空间分隔符. 方法名是给出类的方法名. 格式是一致于HotSpot - XX:+PrintComplation 选项

jinfo:Java配置信息工具

jinfo(JVM Configuration info)这个命令作用是实时查看和调整虚拟机运行参数。 之前的jps -v口令只能查看到显示指定的参数,如果想要查看未被显示指定的参数的值就要使用jinfo口令

命令格式

jinfo [option] [args] LVMID

option参数

  • -flag : 输出指定args参数的值

  • -flags : 不需要args参数,输出所有JVM参数的值

  • -sysprops : 输出系统属性,等同于System.getProperties()

命令:jinfo -flag [+|-]name pid
描述:开启或者关闭对应名称的参数

命令:jinfo -flag name pid
描述:输出对应名称的参数

jmap:Java内存映像工具

命令jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。

参数:

option: 选项参数

pid: 需要打印配置信息的进程ID。

executable: 产生核心dump的Java可执行文件。

core: 需要打印配置信息的核心文件。

server-id 可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。

remote server IP or hostname 远程调试服务器的IP地址或主机名。

option:

no option: 查看进程的内存映像信息,类似 Solaris pmap 命令。
heap: 显示Java堆详细信息
histo[:live]: 显示堆中对象的统计信息
clstats:打印类加载器信息
finalizerinfo: 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
dump:<dump-options>:生成堆转储快照
F: 当-dump没有响应时,使用-dump或者-histo参数. 在这个模式下,live子参数无效.
help:打印帮助信息
J<flag>:指定传递给运行jmap的JVM的参数

示例一:命令:jmap pid
描述:查看进程的内存映像信息,类似 Solaris pmap 命令

示例二:命令:jmap -heap pid
描述:显示Java堆详细信息

打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和各内存区域内存使用信息

示例三:命令:jmap -histo:live pid
描述:显示堆中对象的统计信息

其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live子选项,则只计算活动的对象。

示例四:命令:jmap -histo:live

示例五:命令:jmap -dump:format=b,file=heapdump.phrof pid
描述:生成堆转储快照dump文件。

以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。

jhat:虚拟机堆转储快照分析工具

jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。

jhat内置了一个微型的HTTP/Web服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。

实际上,jhat工作中不常使用。可以使用VisualVM等。

jstack:Java堆栈跟踪工具

jstack [-l] pid

#查看进程下的线程情况

top -Hp pid  

#线程ID转码

printf "%x\n" 线程id

 #定位线程

jstack -l <pid> | grep <thread-hex-id> -A 10

可视化工具分析

GCview

GC日志分析工具

JVisualVM

JVisualVM功能非常强大,可以对堆内存进行dump、快照以及性能可视化分析,也可以安装插件对堆外内存进行分析

Java分析诊断神奇Arthas

下一章节咱么详细实战

关注公众号,发送 yys 免费获取《云原生架构白皮书》。

应用配置文件敏感信息还在裸奔?聊聊敏感信息加密策略_springboot

猜你喜欢

转载自blog.csdn.net/sundehui01/article/details/121610136