【JVM】JVM参数释义

0、前言

JVM对内存的自动管理(内存分配和垃圾回收)使得Java程序员可以较少地关注JVM的内存状态,更过地专注于系统的业务逻辑开发。然而这一优势也带来了一定的弊端,Java程序员对内存的控制程度是比较弱的,系统状态一旦发生异常,异常的原因查找及定位相对来说成本就比较高,这就要求程序员和运维人员能够通过一定的方法在JVM运行前合理配置,运行中有效观察,保证一个服务的可用性与稳定性。

"一定的方法"就是指JVM相关的参数。笔者通过本文,和读者朋友讨论JVM参数及其含义,并附一个JVM调优的案例,辅以相关参数的说明。

1、JVM参数

1.1、JVM堆参数

参数名称 含义 默认值 说明
-Xms 初始堆大小 物理内存的1/64(<1GB) 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制。
-Xmx 最大堆大小 物理内存的1/4(<1GB) 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。
-Xmn(-XX:MaxNewSize) 年轻代最大值 此处的大小是(eden+ 2 survivor space),与jmap -heap中显示的New gen是不同的。
整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。增大年轻代后,将会减小年老代大小。
此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
-XX:NewSize 设置年轻代初始化内存
-XX:MaxNewSize 年轻代最大值
-XX:PermSize 持久代(perm gen)初始值 物理内存的1/64
-XX:MaxPermSize 设置持久代最大值 物理内存的1/4
-Xss 每个线程的堆栈大小 JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。
在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
一般小的应用, 如果栈不是很深, 应该是128k够用的。大的应用建议使用256k。
这个选项对性能影响比较大,需要严格的测试。
和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"” -Xss is translated in a VM flag named ThreadStackSize” 一般设置这个值就可以了。
-XX:ThreadStackSize Thread Stack Size (0 means use default stack size)
Sparc: 512;
Solaris x86: 320 (was 256 prior in 5.0 and earlier);
Sparc 64 bit: 1024;
Linux amd64: 1024 (was 0 in 5.0 and earlier);
all others 0
-XX:NewRatio 年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) -XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。
-XX:SurvivorRatio Eden区与Survivor区的大小比值 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
-XX:LargePageSizeInBytes 内存页的大小 不可设置过大, 会影响Perm的大小
=128m
-XX:+UseFastAccessorMethods 原始类型的快速优化
XX:TLABWasteTargetPercent TLAB占eden区的百分比 1%

1.2、JVM垃圾回收器参数

JVM给出了3种选择:串行收集器、并行收集器、并发收集器。串行收集器只适用于小数据量的情况,所以生产环境的选择主要是并行收集器和并发收集器。
默认情况下JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前系统配置进行智能判断。

1.2.1、串行收集器

  • -XX:+UseSerialGC:设置串行收集器。

1.2.2、并行收集器(吞吐量优先)

  • -XX:+UseParallelGC:设置为并行收集器。此配置仅对年轻代有效。即年轻代使用并行收集,而年老代仍使用串行收集。
  • -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时有多少个线程一起进行垃圾回收。此值建议配置与CPU数目相等。
  • -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0开始支持对年老代并行收集。
  • -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间(单位毫秒)。如果无法满足此时间,JVM会自动调整年轻代大小,以满足此时间。
  • -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动调整年轻代Eden区大小和Survivor区大小的比例,以达成目标系统规定的最低响应时间或者收集频率等指标。此参数建议在使用并行收集器时,一直打开。

1.2.3、并发收集器(响应时间优先)

  • -XX:+UseConcMarkSweepGC:即CMS收集,设置年老代为并发收集。CMS收集是JDK1.4后期版本开始引入的新GC算法。它的主要适合场景是对响应时间的重要性需求大于对吞吐量的需求,能够承受垃圾回收线程和应用线程共享CPU资源,并且应用中存在比较多的长生命周期对象。CMS收集的目标是尽量减少应用的暂停时间,减少Full GC发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代内存。
  • -XX:+UseParNewGC:设置年轻代为并发收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此参数。
  • -XX:CMSFullGCsBeforeCompaction=0:由于并发收集器不对内存空间进行压缩和整理,所以运行一段时间并行收集以后会产生内存碎片,内存使用效率降低。此参数设置运行0次Full GC后对内存空间进行压缩和整理,即每次Full GC后立刻开始压缩和整理内存。
  • -XX:+UseCMSCompactAtFullCollection:打开内存空间的压缩和整理,在Full GC后执行。可能会影响性能,但可以消除内存碎片。
  • -XX:+CMSIncrementalMode:设置为增量收集模式。一般适用于单CPU情况。
  • -XX:CMSInitiatingOccupancyFraction=70:表示年老代内存空间使用到70%时就开始执行CMS收集,以确保年老代有足够的空间接纳来自年轻代的对象,避免Full GC的发生。

1.2.4、其它垃圾回收参数

  • -XX:+ScavengeBeforeFullGC:年轻代GC优于Full GC执行。
  • -XX:-DisableExplicitGC:不响应 System.gc() 代码,这个参数需要严格的测试。
  • -XX:+UseThreadPriorities:启用本地线程优先级API。即使 java.lang.Thread.setPriority() 生效,不启用则无效。
  • -XX:SoftRefLRUPolicyMSPerMB=0:软引用对象在最后一次被访问后能存活0毫秒(JVM默认为1000毫秒)。
  • -XX:TargetSurvivorRatio=90:允许90%的Survivor区被占用(JVM默认为50%)。提高对于Survivor区的使用率。
  • -XX:MaxTenuringThreshold:垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代里被回收的概率。该参数只有在串行GC时才有效。
  • -Xnoclassgc:禁用垃圾回收
  • -XX:PretenureSizeThreshold:对象超过多大是直接在旧生代分配。新生代采用Parallel Scavenge GC时无效。另一种直接在旧生代分配的情况是大的数组对象,且数组中无外部引用对象。
  • -XX:+CollectGen0First:FullGC时是否先YGC,默认值是false。
  • -XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)。

1.3、JVM辅助信息参数

参数名称 含义 默认值 说明
-XX:+PrintGC 输出形式:
[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs]
-XX:+PrintGCDetails 输出形式:
[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]
[GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
-XX:+PrintGCTimeStamps
-XX:+PrintGC:PrintGCTimeStamps 可与-XX:+PrintGC -XX:+PrintGCDetails混合使用
输出形式:
11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
-XX:+PrintGCApplicationStoppedTime 打印垃圾回收期间程序暂停的时间。可与上面混合使用 输出形式:
Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中断的执行时间。可与上面混合使用 输出形式:
Application time: 0.5291524 seconds
-XX:+PrintHeapAtGC 打印GC前后的详细堆栈信息。
-Xloggc:filename 把相关日志信息记录到文件以便分析。与上面几个配合使用。
-XX:+PrintClassHistogram garbage collects before printing the histogram.
-XX:+PrintTLAB 查看TLAB空间的使用情况。
XX:+PrintTenuringDistribution 查看每次minor GC后新的存活周期的阈值。 Desired survivor size 1048576 bytes, new threshold 7 (max 15) new threshold 7即标识新的存活周期的阈值为7。

1.4、JVM其他参数

参数名称 含义 默认值 说明
-XX:+AggressiveOpts 加快编译
-XX:+UseBiasedLocking 锁机制的性能改善

2、案例-JVM调优参数说明

2.1、服务器配置

8 CPU, 8G MEM, JDK 1.6.X

2.2、参数方案

-server -Xmx3550m -Xms3550m -Xmn1256m -Xss128k -XX:SurvivorRatio=6 -XX:MaxPermSize=256m -XX:ParallelGCThreads=8 -XX:MaxTenuringThreshold=0 -XX:+UseConcMarkSweepGC

2.3、调优说明

  • -Xmx 与 -Xms 相同以避免JVM反复重新申请内存。-Xmx 的大小约等于系统内存大小的一半,即充分利用系统资源,又给予系统安全运行的空间。
  • -Xmn1256m 设置年轻代大小为1256MB。此值对系统性能影响较大,Sun官方推荐配置年轻代大小为整个堆的3/8。
  • -Xss128k 设置较小的线程栈以支持创建更多的线程,支持海量访问,并提升系统性能。
  • -XX:SurvivorRatio=6 设置年轻代中Eden区与Survivor区的比值。系统默认是8,根据经验设置为6,则2个Survivor区与1个Eden区的比值为2:6,一个Survivor区占整个年轻代的1/8。
  • -XX:ParallelGCThreads=8 配置并行收集器的线程数,即同时8个线程一起进行垃圾回收。此值一般配置为与CPU数目相等。
  • -XX:MaxTenuringThreshold=0 设置垃圾最大年龄(在年轻代的存活次数)。如果设置为0的话,则年轻代对象不经过Survivor区直接进入年老代。对于年老代比较多的应用,可以提高效率;如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概率。根据被海量访问的动态Web应用之特点,其内存要么被缓存起来以减少直接访问DB,要么被快速回收以支持高并发海量请求,因此其内存对象在年轻代存活多次意义不大,可以直接进入年老代,根据实际应用效果,在这里设置此值为0。
  • -XX:+UseConcMarkSweepGC 设置年老代为并发收集。CMS(ConcMarkSweepGC)收集的目标是尽量减少应用的暂停时间,减少Full GC发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代内存,适用于应用中存在比较多的长生命周期对象的情况。
发布了11 篇原创文章 · 获赞 5 · 访问量 6884

猜你喜欢

转载自blog.csdn.net/C1248770189/article/details/105033915