JVM技术专题深入研究JVM性能参数大全「介绍篇」

Posted 浩宇の天尚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM技术专题深入研究JVM性能参数大全「介绍篇」相关的知识,希望对你有一定的参考价值。


功能开关参数

参数默认值功能
-XX:-AllowUserSignalHandlers限于Linux和Solaris,默认不启用允许为java进程安装信号处理器,信号处理参见类:sun.misc.Signal, sun.misc.SignalHandler
-XX:+DisableExplicitGC默认启用禁止在运行期显式地调用System.gc()
-XX:+FailOverToOldVerifierJava6新引入选项,默认启用如果新的Class校验器检查失败,则使用老的校验器
-XX:+HandlePromotionFailurejava5以前是默认不启用,java6默认启用是否开启新生代收集担保
-XX:+UseSpinning对于java6来说已经默认启用了是否开启自旋锁机制
-XX:+MaxFDLimit默认启用设置java进程可用文件描述符为操作系统允许的最大值。
-XX:-RelaxAccessControlCheck默认不启用在Class校验器中,放松对访问控制的检查,作用与reflection里的setAccessible类似
-XX:+ScavengeBeforeFullGC默认启用在Full GC前触发一次Minor GC
-XX:-UseConcMarkSweepGC默认不启用启用CMS低停顿垃圾收集器,减少FGC的暂停时间
-XX:+UseGCOverheadLimit默认启用限制GC的运行时间。如果GC耗时过长,就抛OOM
-XX:-UseParallelGC-server时启用,其他情况下,默认不启用策略为新生代使用并行清除,年老代使用单线程Mark-Sweep-Compact的垃圾收集器
-XX:-UseParallelOldGC默认不启用策略为老年代和新生代都使用并行清除的垃圾收集器
-XX:-UseSerialGC-client时启用,其他情况下,默认不启用使用串行垃圾收集器
-XX:+UseTLAB1.4.2以前和使用-client选项时,默认不启用,其余版本默认启用启用线程本地缓存区
-XX:+UseThreadPriorities默认启用使用本地线程的优先级
-XX:+AggressiveOptsJDK 5 update 6后引入,但需要手动启用, JDK6默认启用启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等
-XX:+UseBiasedLockingJDK 5 update 6后引入,但需要手动启用, JDK6默认启用启用偏向锁
-XX:+UseFastAccessorMethods默认启用优化原始类型的getter方法性能(get/set:Primitive Type)
-XX:+UseStringCache默认开启启用缓存常用的字符串。

性能参数

参数默认值或限制说明
-XX:CompileThreshold=100001000通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码
-XX:PreBlockSpin=10-XX:+UseSpinning 必须先启用,对于java6来说已经默认启用了,这里默认自旋10次控制多线程自旋锁优化的自旋次数
-XX:LargePageSizeInBytes=4m默认4m, amd64位:2m设置堆内存的内存页大小
-XX:MaxHeapFreeRatio=7070GC后,如果发现空闲堆内存占到整个预估上限值的70%,则收缩预估上限值
-XX:MaxNewSize=size1.3.1 Sparc: 32m, 1.3.1 x86: 2.5m新生代占整个堆内存的最大值
-XX:MaxPermSize=64m5.0以后: 64 bit VMs会增大预设值的30%, 1.4 amd64: 96m, 1.3.1 -client: 32m, 其他默认 64mPerm(俗称方法区)占整个堆内存的最大值
-XX:MaxPermSize=64m5.0以后: 64 bit VMs会增大预设值的30%, 1.4 amd64: 96m, 1.3.1 -client: 32m, 其他默认 64mPerm(俗称方法区)占整个堆内存的最大值
-XX:MinHeapFreeRatio=4040GC后,如果发现空闲堆内存占到整个预估上限值的40%,则增大上限值
-XX:NewRatio=2Sparc -client: 8, x86 -server: 8, x86 -client: 12, -client: 4 (1.3),8 (1.3.1+), x86: 12, 其他默认 2新生代和年老代的堆内存占用比例, 例如2表示新生代占年老代的1/2,占整个堆内存的1/3
-XX:NewSize=2.125m5.0以后: 64 bit Vms 会增大预设值的30%, x86: 1m, x86, 5.0以后: 640k, 其他默认 2.125m新生代预估上限的默认值
-XX:SurvivorRatio=8Solaris amd64: 6, Sparc in 1.3.1: 25, Solaris platforms 5.0以前: 32, 其他默认 8Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存,即1/10的新生代内存,为什么不是1/9?因为我们的新生代有2个survivor,即S0和S1。所以survivor总共是占用新生代内存的 2/10,Eden与新生代的占比则为 8/10
-XX:TargetSurvivorRatio=5050实际使用的survivor空间大小占比。默认是50%,最高90%

Trace跟踪参数

参数默认值或限制说明
-verbose:gc -XX:+printGC打印GC的简要信息搭配使用最好
-XX:+PrintHeapAtGC关闭打印GC详细信息当发生GC
-XX:+PrintGCDetails关闭打印GC详细信息
-XX:+PrintGCTimeStamps关闭打印CG发生的时间戳
-Xloggc:log/gc.log指定GC log的位置,以文件输出
XX:+TraceClassLoading监控类的加载监控类的加载
-XX:+PrintClassHistogram打印类的信息打印类的信息
-XX:-CITime打印发费在JIT编译上的时间

堆分配参数

参数默认值或限制说明
-Xmx –Xms分别是1/4 和 1/64指定最大堆和最小堆
-Xmn关闭设置新生代大小
-XX:NewRatio2新生代(eden+2*s)和老年代(不包含永久区)的比值 ,4,表示新生代:老年代=1:4,即新生代占整个堆的1/5
-XX:SurvivorRatio(幸存代)8设置两个Survivor区和eden的比值
-XX:+HeapDumpOnOutOfMemoryErrorOOM时导出堆到文件  根据这个文件,我们可以看到系统dump时发生了什么
-XX:HeapDumpPath=./java_pid.hprof导出OOM的路径
-XX:PermSize -XX:MaxPermSize设置永久区的初始空间和最大空间。也就是说,jvm启动时,永久区一开始就占用了PermSize大小的空间,如果空间还不够,可以继续扩展,但是不能超过MaxPermSize,否则会OOM。
-XX:OnOutOfMemoryError=”;”-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p //p代表的是当前进程的pid ,当发生OOM的时候进行调用脚本等功能
-XX:OnError=”;当发生错误时执行用户指定的命令
-XX:-PrintTenuringDistribution打印分配内存时候的年龄
-XX:+UseCompressedOops启动压缩机制
-XX:InitialTenuringThreshold=7设置初始的对象在新生代中最大存活次数
-XX:MaxTenuringThreshold=设置对象在新生代中最大的存活次数,最大值15,并行回收机制默认为15,CMS默认为4

栈的分配参数

-Xss128K 设置栈空间的大小。通常只有几百K  决定了函数调用的深度  每个线程都有独立的栈空间  局部变量、参数 分配在栈上


调优总结

GC垃圾回收流程

数据会首先分配到Eden区当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象),当Eden没有足够空间的时候就会触发jvm发起一次Minor GC。如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代 中了,当然晋升老年代的年龄是可以设置的。

年轻代大小选择

  • 响应时间优先的应用尽可能设大年轻代大小,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象
  • 吞吐量优先的应用尽可能的设置大,可能到达GBit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用

年老代大小选择

  • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。

最优化的方案,一般需要参考以下数据获得:

  • 并发垃圾收集信息
  • 持久代并发收集次数
  • 传统GC信息
  • 花在年轻代和年老代回收上的时间比例
  • 减少年轻代和年老代花费的时间,一般会提高应用的效率

  • 吞吐量优先的应用一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

  • 较小堆引起的碎片问题因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。

当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。(此时还有可能会存在Concurrent Prometion failure)

如果出现“碎片”,可能需要进行如下配置:

  • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
  • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
  • -XX:MaxHeapFreeRatio=30

以上是关于JVM技术专题深入研究JVM性能参数大全「介绍篇」的主要内容,如果未能解决你的问题,请参考以下文章

JVM技术专题深入研究JVM挖掘知识体系系列「补充篇」

JVM技术专题深入研究字符串常量池的相关知识体系「入门篇」

JVM技术专题深入研究JMM的实现原理之Happens-Before原则和As-If-Serial语义「入门篇」

Java技术专题-JVM研究系列,JVM深入研究挖掘课题

Java技术专题-JVM研究系列,JVM深入研究挖掘课题

Java技术专题-JVM研究系列(24)深入挖掘Java对象的内存结构