jvm 调优参数

JVM常用调优参数 ——JVM篇

这篇文章的大佬实在是太👍了!部分待更新内容等我先把其他消化理解了先.

性能调优

性能调优包含多个层次:架构调优、代码调优、JVM调优、数据库调优、操作系统调优等等
架构调优和代码调优是JVM调优的基础,其中架构调优是对系统影响最大的
性能调优基本步骤:

  • 发现性能瓶颈
  • 明确优化目标
  • 性能调优
  • 通过监控及数据统计工具获得调优后数据
  • 确认是否达到目标

何时进行JVM调优

  • Heap内存(老年代)持续上涨达到设置的最大内存值;
  • Full GC 次数频繁;
  • GC 停顿时间过长(超过1秒)
  • 应用出现OutOfMemory等内存异常;
  • 应用中有使用本地缓存且占用大量内存空间;
  • 系统吞吐量与响应性能不高或不降。

JVM调优基本原则

  • 大多数的Java应用不需要进行JVM优化;
  • 大多数导致GC问题的原因是代码层面的问题导致的(代码层面);
  • 上线之前,应先考虑将机器的JVM参数设置到最优;
  • 减少创建对象的数量(代码层面);
  • 减少使用全局变量和大对象(代码层面);
  • 优先架构调优和代码调优,JVM优化是不得已的手段(代码、架构层面);
  • 分析GC情况优化代码比优化JVM参数更好(代码层面)。

最有效的优化手段是架构和代码层面的优化,而JVM优化则是最后不得已的手段,也可以说是对服务器配置的最后一次“压榨”。

JVM调优目标

调优的最终目的都是为了令应用程序使用最小的硬件消耗来承载更大的吞吐JVM调优主要是针对垃圾收集器的收集性能优化令运行在虚拟机上的应用能够使用更少的内存以及延迟获取更大的吞吐量

  • 延迟:GC低停顿和GC低频率;
  • 低内存占用;
  • 高吞吐量。

JVM调优量化目标

JVM调优的量化目标参考实例:

  • Heap 内存使用率 <= 70%;
  • Old generation 内存使用率 <= 70%;
  • avgpause <= 1秒;
  • Full GC 次数 0 或 avg pause interval >= 24小时。

注意:不同应用的JVM调优量化目标是不一样的。

JVM调优的步骤

JVM调优可通过以下步骤进行:

  • 分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点;
  • 确定JVM调优量化目标;
  • 确定JVM调优参数(根据历史JVM参数来调整);
  • 依次调优内存、延迟、吞吐量等指标;
  • 对比观察调优前后的差异;
  • 不断的分析和调整,直到找到合适的JVM参数配置;
  • 找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。

以上操作步骤中,某些步骤是需要多次不断迭代完成的。一般是从满足程序的内存使用需求开始的,之后是时间延迟的要求,最后才是吞吐量的要求,要基于这个步骤来不断优化,每一个步骤都是进行下一步的基础,不可逆行之。

JVM参数

-XX 参数被称为不稳定参数。此类参数的设置很容易引起JVM性能上的差异,使 JVM 存在极大的不稳定性。如果此类参数设置合理将大大提高JVM的性能及稳定性

不稳定参数语法规则包含以下内容:

  • 布尔类型参数值
    • -XX:+ 表示启用该选项
    • -XX:- 表示关闭该选项
  • 数字类型参数值:
    • XX: = 给选项设置一个数字类型值,可跟随单位。
      • 例如:‘m’或‘M’表示兆字节;‘k’或‘K’千字节;‘g’或‘G’千兆字节。32K与32768是相同大小的。
  • 字符串类型参数值:
    • -XX: = 给选项设置一个字符串类型值,通常用于指定一个文件、路径或一系列命令列表。
      • 如:-XX:HeapDumpPath=./dump.core

JVM参数解析及调优

Java7及以前版本的示例:

-Xmx4g 
–Xms4g
–Xmn1200m
–Xss512k
-XX:NewRatio=4
-XX:SurvivorRatio=8
-XX:PermSize=100m
-XX:MaxPermSize=256m
-XX:MaxTenuringThreshold=15

在Java8中永久代的参数-XX:PermSize和-XX:MaxPermSize已经失效。

参数解析:

  • -Xmx4g:堆内存最大值为4GB
  • -Xms4g:初始化堆内存大小为4GB
  • -Xmn1200m:设置年轻代大小为1200MB
    • 增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
  • -Xss512k:设置每个线程的堆栈大小。
    • JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。应根据应用线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
  • -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
    • 设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
  • -XX:SurvivorRatio=8: 设置年轻代中Eden区与Survivor区的大小比值。
    • 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
  • -XX:PermSize=100m:初始化永久代大小为100MB。
  • -XX:MaxPermSize=256m:设置持久代大小为256MB。
  • -XX:MaxTenuringThreshold=15:设置垃圾最大年龄。
    • 如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

新生代、老生代、永久代的参数,如果不进行指定,虚拟机会自动选择合适的值,同时也会基于系统的开销自动调整。

可调优参数:

  • -Xms:初始化堆内存大小,默认为物理内存的1/64(小于1GB)。
  • -Xmx:堆内存最大值。默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。
  • -Xmn:新生代大小,包括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预清理阶段执行达到这个时间时就会结束。

注意:在设置的时候,如果关注性能开销的话,应尽量把永久代的初始值与最大值设置为同一值,因为永久代的大小调整需要进行FullGC才能实现。

内存优化示例


以上gc日志中,在发生fullGC之时,整个应用的堆占用以及GC时间。为了更加精确需多次收集,计算平均值。或者是采用耗时最长的一次FullGC来进行估算。上图中,老年代空间占用在93168kb(约93MB),以此定为老年代空间的活跃数据。则其他堆空间的分配,基于以下规则来进行。

  • java heap:参数-Xms和-Xmx,建议扩大至3-4倍FullGC后的老年代空间占用。
  • 永久代:-XX:PermSize和-XX:MaxPermSize,建议扩大至1.2-1.5倍FullGc后的永久代空间占用。
  • 新生代:-Xmn,建议扩大至1-1.5倍FullGC之后的老年代空间占用。
  • 老年代:2-3倍FullGC后的老年代空间占用。

基于以上规则,则对参数定义如下:

-Xms373m -Xmx373m //4*93=372
-Xmn140m //1.5*93=139.5
-XX:PermSize=5m -XX:MaxPermSize=5m //1.5*3=4.5

吞吐量调优

调优工具

借助GCViewer日志分析工具,可以非常直观地分析出待调优点。

  • Memory,分析Totalheap、Tenuredheap、Youngheap内存占用率及其他指标,理论上内存占用率越小越好;
  • Pause,分析Gc pause、Fullgc pause、Total pause三个大项中各指标,理论上GC次数越少越好,GC时长越小越好;

总结JVM参数使用手则

内存相关

GC策略相关

GC日志相关

异常相关

问题定位及优化相关