jvm 参数设置与分析

2016-03-21 11:46:38   最后更新: 2016-03-25 20:28:00   访问数量:1154




之前的日志中介绍了 jvm 内存管理和垃圾收集的相关内容,结合这些理论知识,通过合理设置参数才能将系统的性能得以提升

 

基本的设置参数

JVM 设置参数的主要含义
参数名称含义默认值说明
-Xms最小堆大小物理内存的 1/64(<1GB)空闲堆内存小于40%(通过 MinHeapFreeRatio 参数可调整该阈值)时,jvm 会增大堆直到 -Xmx
-Xmx最大堆大小物理内存的 1/4(<1GB)空闲堆内存大于70%(通过 MaxHeapFreeRatio 参数可以调整该阈值)时,jvm 会减小堆直到 -Xms
-Xmn新生代大小指 Eden 与两个 Survivor 空间之和,Sun 官方推荐配置为整个堆的 3/8
-XX:PermSize方法区(永久代)大小物理内存的 1/64-
-Xss每个线程的堆栈大小1M-
-XX:ThreadStackSize线程堆栈大小1M主线程以 -Xss 设置为主,其他线程以该设置为主,一般采用默认值即可
-XX:NewRadio新生代与老年代大小的比值Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置
-XX:SurvivorRatioEden 区域 Survivor 区大小的比值-
-XX:LargePageSizeInBytes内存页大小128M不可设置过大
-XX:+UseFastAccessorMethods是否使用原始类型的快速优化-
-XX:+DisableExplicitGC是否关闭 System.gc()-
-XX:MaxTenuringThreshold垃圾最大年龄N 次没有被回收的新生代资源自动放入老年代,只有使用串行GC时才有效
-XX:MaxGCPauseMillis最大停顿时间-每次年轻代垃圾收集的最长时间
-Xnoclassgc金庸垃圾回收-
-XX:SoftRefLRUPolicyMSPerMB没M堆内存中软引用存活时间1s-
-XX:PretenureSizeThreshold对象超过多大自动在老年代分配0采用 Parallel Scavenge GC 时无效
-XX:TLABWasteTargetPercentTLAB 占 eden 区的百分比1%-
-XX:+CollectGen0FirstFullGC时是否先YGCfalse-

 

并行收集相关的参数

JVM 并行GC的设置参数
参数名称含义默认值说明
-XX:+UseParGC使用 ParNew 收集器进行新生代收集false与 -XX:+UseConcMarkSweepGC 相同
-XX:ParallelGCThreads并行收集线程数-指定并行 GC 下的垃圾收集线程数,最好配置为与 CPU 数相等
-XX:+UseParallelOldGC设置老年代收集器为 Parallel OldJDK1.6 起开始提供-
-XX:+UseAdaptiveSizePolicy自动选择年轻代大小及 Survivor 比例false建议在使用并行收集器一直打开
-XX:GCTimeRatio设置垃圾回收时间占用程序运行时间百分比大于 0 小于 100,使用 Parallel Scavenge 时设置
-XX:+UseAdaptiveSizePolicy是否自动根据当前系统情况决定最大吞吐量的限制false使用 Parallel Scavenge 时设置
-XX:+ScavengeBeforeFullGCFull GC前调用YGCtrue-

 

CMS 相关参数

JVM CMS GC 的设置参数
参数名称含义默认值说明
-XX:+UseConcMarkSweepGC启用 CMS GCfalse-
-XX:CMSFullGCsBeforeCompaction运行多少次 GC 后进行一次内存压缩(碎片整理)--
-XX:+CMSParallelRemarkEnabled降低标记停顿false-
-XX+UseCMSCompactAtFullCollection是否启用内存压缩(碎片整理)-建议开启
-XX:+UseCMSInitiatingOccupancyOnly手动触发 CMSfalse禁止 HotSpot 自动触发 CMS GC
-XX:CMSInitiatingOccupancyFractionGC 触发阈值(百分比)1.5为68,1.6为92内存使用达到阈值则开始 GC,设置过大会有可能造成失败而进行 full GC
-XX:+CMSIncrementalMode设置为增量模式false运用于单CPU下,在 CMS 运行途中暂停,继续运行用户线程,下次增量 GC
-XX:CMSClassUnloadingEnabled垃圾回收清理方法区时移除不再使用的 classes--
-XX:+CMSPermGenSweepingEnabled是否清理方法区(永久代)-默认不清理

 

年轻代大小选择

  1. 响应时间优先的应用 -- 尽可能增大年轻代大小,这也意味着老年代的大小会相对减少,因此同时要减少到达老年代的对象
  2. 吞吐量优先应用 -- 尽可能增大年轻代,可以选择并行垃圾收集,适合 8CPU 以上应用

 

无论如何,谨记不能将新生代设置过小,否则会造成新生代 GC 频繁,甚至让新生代对象直接进入老年代,从而触发 full GC

 

老年代大小选择

  1. 响应时间优先的应用 -- 通常老年代使用 CMS 进行并发收集,所以老年代不能设计过小,否则会因为内存过多造成频繁 full GC;如果设计过大,则需要较长的收集,因此需要结合并发收集信息、持久化并发收集次数、传统GC信息、年轻代和老年代的时间比例考虑具体的内存大小
  2. 吞吐量优先应用 -- 这样的应用通常需要大年轻代 + 小老年代,这样可以尽可能回收大部分短期对象,减少中期对象,而老年代存放长期存活对象

 

老年代的内存碎片问题

如果使用 CMS 作为老年代收集器,那么由于他采取的标记清除算法,通常会造成碎片,如果最终空间不足,则会触发一次 full GC

针对这种情况,需要进行如下配置:

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

 

其他事项

  1. linux 64 位操作系统中,jdk 消耗内存更多,执行速度更慢,但吞吐量更大
  2. XMX 和 XMS 设置一样大,MaxPermSize 和 MinPermSize 设置一样大,这样可以减轻伸缩堆大小带来的压力
  3. 使用CMS的好处是用尽量少的新生代,经验值是128M-256M, 然后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间非常的短,2G的内存, 大约20-80ms的应用程序停顿时间
  4. 系统停顿的时候可能是GC的问题也可能是程序的问题,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多问题。
  5. 如果用了缓存,那么年老代应该大一些
  6. 采用并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿

 

产生 promotion failed 可能是两个原因引起的:

  1. 新生代的 survivor 不足,年轻代中很多对象等待放入 survior 内存,致使 Survivor 空间不足,这些内存被放入老年代
  2. 老年代没有足够的内存接纳来自年轻代的对象

 

解决这个问题,就要从这两个原因着手:

  1. 增大 Survivor 区域大小,设置 -XX:SurvivorRatio=1
  2. 降低 CMSInitiatingOccupancyFraction(如设置为 70),让老年代在较低阈值时被回收

 

可以推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的情况,即:

(Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2))

得到:

CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)*100

 

http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html

 






技术帖      虚拟机      技术分享      java      jvm      gc      方法区      垃圾回收      新生代      老年代      参数      设置      永久代     


京ICP备15018585号