JVM 的常用参数 以及 JVM参数调优

JVM 的常用参数 以及 JVM参数调优

 

 

 

1、常用参数

JVM的参数非常之多,这里只列举比较重要的几个,通过各种各样的搜索引擎也可以得知这些信息。

参数名称

含义

默认值

说明

-Xms

初始堆大小

物理内存的1/64(<1GB)

默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.

使用方法:-Xms2g 或 -XX:InitialHeapSize=2048m

-Xmx

最大堆大小

物理内存的1/4(<1GB)

默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制


使用方法:-Xmx2g 或 -XX:MaxHeapSize=2048m


-Xmn

新生代最大值(1.4or later)

 

注意:此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不同的。整个堆大小=年轻代大小 + 老年代大小 + 持久代(永久代)大小.增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8

使用方法:-Xmn512m 或 -XX:MaxNewSize=512m

-XX:NewSize

设置年轻代大小(for 1.3/1.4)

 

如果我们要为 新生代分配 最小256m 的内存,最大 1024m的内存我们的参数应该这样来写: 


-XX:NewSize=256m
-XX:MaxNewSize=1024m


-XX:MaxNewSize

年轻代最大值(for 1.3/1.4)

 

 

-XX:PermSize

设置持久代(perm gen)初始值

物理内存的1/64

jdk1.8已废弃 

-XX:MaxPermSize

设置持久代最大值

物理内存的1/4

jdk1.8已废弃 


-XX:MetaspaceSize=N
-XX:MaxMetaspaceSize=N


默认为机器的本地内存 

 

// 设置 Metaspace 的初始值(jdk1.8后用于替换permSize)
-XX:MetaspaceSize=N
// 元数据区最大值,如果不指定大小的话,虚拟机会耗尽所有可用的系统直接内存。(jdk1.8后用户替换maxPermSize)
-XX:MaxMetaspaceSize=N

-Xss

线程栈最大值

 

JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.根据应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长)和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了

使用方法:-Xss256k 或 -XX:ThreadStackSize=256k

-XX:NewRatio

年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)

 

-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。

-XX:SurvivorRatio

Eden区与Survivor区的大小比值

 

设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10

-XX:+DisableExplicitGC

关闭System.gc()

 

这个参数需要严格的测试

-XX:PretenureSizeThreshold

对象超过多大是直接在旧生代分配

0

设置该参数,可以使大于这个值的对象直接在老年代分配,避免在Eden区和Survivor区发生大量的内存复制,该参数只对Serial和ParNew收集器有效,Parallel Scavenge并不认识该参数。

使用方法:-XX:PretenureSizeThreshold=1000000 

-XX:ParallelGCThreads

并行收集器的线程数

 

此值最好配置与处理器数目相等 同样适用于CMS

-XX:MaxGCPauseMillis

每次年轻代垃圾回收的最长时间(最大暂停时间)

 

如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值.


-XX:MaxTenuringThreshold


 最大值15

15 

设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代.
    对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,
    则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,
    增加在年轻代即被回收的概率。该参数只有在串行GC时才有效


-XX:+HeapDumpOnOutOfMemoryError
 -XX:HeapDumpPath


 OOM时DUMP内存

 

-XX:HeapDumpPath=你要输出的日志路径

 可以通过jinfo -flag [+|-]HeapDumpOnOutOfMemoryError 或 jinfo -flag HeapDumpOnOutOfMemoryError= 来动态开启或设置值

XX:+UseSerialGC

年轻代使用Serial垃圾收集器

 

开启 -XX:+UseSerialGC
使用经验:不推荐使用,性能太差,老年代将会使用SerialOld垃圾收集器
-XX:+UseSerialGC

-XX:+UseParallelGC

年轻代使用Parallel Scavenge垃圾收集器

 

开启 -XX:+UseParallelGC使用经验:Linux下1.6,1.7,1.8默认开启,老年代将会使用SerialOld垃圾收集器

-XX:+UseParallelOldGC

年轻代使用Parallel Scavenge收集器

 

开启 -XX:+UseParallelOldGC使用经验:老年代将会使用Parallel Old收集器

-XX:+UseConcMarkSweepGC

老年代使用CMS收集器(如果出现"Concurrent Mode Failure",会使用SerialOld收集器)

 

开启 -XX:+UseConcMarkSweepGC使用经验:年轻代将会使用ParNew收集器

-XX:+UseG1GC

使用G1垃圾收集器

 

使用G1垃圾收集器

-XX:+CollectGen0First

 

 

设置FullGC时是否先YGC,默认值是false

-Xloggc

GC日志文件路径

 

使用方法:-Xloggc:/data/gclog/gc.log

-XX:+UseGCLogFileRotation

滚动GC日志文件,须配置Xloggc

 

滚动GC日志文件,须配置Xloggc

-XX:GCLogFileSize=100k

 

 

GC文件滚动大小,需配置UseGCLogFileRotation,设置为0表示仅通过jcmd命令触发

-XX:+PrintGCDetails

 

 

GC时打印更多详细信息,默认关闭。  开启 -XX:+PrintGCDetails

可以通过jinfo -flag [+|-]PrintGCDetails 或 jinfo -flag PrintGCDetails= 来动态开启或设置值

-XX:+PrintGCDateStamps

 

 

GC时打印时间戳信息,默认关闭

可以通过jinfo -flag [+|-]PrintGCDateStamps 或 jinfo -flag PrintGCDateStamps= 来动态开启或设置值

-XX:+PrintTenuringDistribution

 

 

打印存活实例年龄信息,默认关闭

-XX:+PrintGCApplicationStoppedTime

 

 

打印应用暂停时间,默认关闭

-XX:+PrintHeapAtGC

 

 

GC前后打印堆区使用信息,默认关闭

 

2、JVM 堆内存调优

      对JVM进行调优,主要就是堆内存那块。所有线程共享数据区大小=新生代大小 + 年老代大小 + 持久代大小(jdk8以前)。持久代一般固定大小为64m。所以java堆中增大年轻代后,将会减小年老代大小(因为老年代的清理是使用fullgc,所以老年代过小的话反而是会增多fullgc的)。此值对系统性能影响较大,Sun官方推荐配置为java堆的3/8 。

2.1、调整最大堆内存和最小堆内存

-Xmx –Xms:指定java堆最大值(默认值是物理内存的1/4(<1GB))和初始java堆最小值(默认值是物理内存的1/64(<1GB))

默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。简单点来说,你不停地往堆内存里面丢数据,等它剩余大小小于40%了,JVM就会动态申请内存空间不过会小于-Xmx,如果剩余大小大于70%,又会动态缩小不过不会小于–Xms。就这么简单

开发过程中,通常会将 -Xms 与 -Xmx两个参数配置成相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。

2.2、调整新生代和老年代的比值

-XX:NewRatio --- 新生代(eden+2*Survivor)和老年代(不包含永久区)的比值

例如:-XX:NewRatio=4,表示新生代:老年代=1:4,即新生代占整个堆的1/5。在Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。

2.3 、调整Survivor区和Eden区的比值

-XX:SurvivorRatio(幸存代)--- 设置两个Survivor区和eden的比值

例如:8,表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10

2.4、 设置年轻代和老年代的大小

-XX:NewSize --- 设置年轻代大小

-XX:MaxNewSize --- 设置年轻代最大值

可以通过设置不同参数来测试不同的情况,反正最优解当然就是官方的Eden和Survivor的占比为8:1:1,然后在刚刚介绍这些参数的时候都已经附带了一些说明,感兴趣的也可以看看。反正最大堆内存和最小堆内存如果数值不同会导致多次的gc,需要注意。

总结:

根据实际事情调整新生代和幸存代的大小,官方推荐新生代占java堆的3/8,幸存代占新生代的1/10

在OOM时,记得Dump出堆,确保可以排查现场问题,通过下面命令你可以输出一个.dump文件,这个文件可以使用VisualVM或者Java自带的Java VisualVM工具。

-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=你要输出的日志路径

一般我们也可以通过编写脚本的方式来让OOM出现时给我们报个信,可以通过发送邮件或者重启程序等来解决。

GC 调优策略中很重要的一条经验总结是这样说的:

将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。

 

3、JVM的栈参数调优

3.1、 调整每个线程栈空间的大小

可以通过-Xss:调整每个线程栈空间的大小

JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

设置线程栈的大小:  -XXThreadStackSize:设置线程栈的大小(0 means use default stack size)

 

4、垃圾收集相关

垃圾回收器

为了提高应用程序的稳定性,选择正确的垃圾收集open in new window算法至关重要。

JVM具有四种类型的GC实现:

  • 串行垃圾收集器
  • 并行垃圾收集器
  • CMS垃圾收集器
  • G1垃圾收集器

可以使用以下参数声明这些实现:

-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseParNewGC
-XX:+UseG1GC

 

5、GC记录

为了严格监控应用程序的运行状况,我们应该始终检查JVM的垃圾回收性能。最简单的方法是以人类可读的格式记录GC活动。

使用以下参数,我们可以记录GC活动:

-XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=< number of log files > 
-XX:GCLogFileSize=< file size >[ unit ]
-Xloggc:/path/to/gc.log