JVM 参数设置

 

 

无论是YGC仍是Full GC,GC过程当中都会对致使程序运行中中断,正确的选择不一样的GC策略,调整JVM、GC的参数,能够极大的减小因为GC工做,而致使的程序运行中断方面的问题,进而适当的提升Java程序的工做效率。可是调整GC是以个极为复杂的过程,因为各个程序具有不一样的特色,如:web和GUI程序就有很大区别(Web能够适当的停顿,但GUI停顿是客户没法接受的),并且因为跑在各个机器上的配置不一样(主要cup个数,内存不一样),因此使用的GC种类也会不一样(如何选择见GC种类及如何选择)。本文将注重介绍JVM、GC的一些重要参数的设置来提升系统的性能。html

       JVM内存组成及GC相关内容请见以前的文章:JVM内存组成 GC策略&内存申请java

JVM参数的含义 实例见实例分析web

参数名称 含义 默认值  
-Xms 初始堆大小 物理内存的1/64(<1GB) 默认(MinHeapFreeRatio参数能够调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.
-Xmx 最大堆大小 物理内存的1/4(<1GB) 默认(MaxHeapFreeRatio参数能够调整)空余堆内存大于70%时,JVM会减小堆直到 -Xms的最小限制
-Xmn 年轻代大小(1.4or lator)   注意
整个堆大小=年轻代大小 + 年老代大小 
增大年轻代后,将会减少年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8
-XX:NewSize 设置年轻代大小(for 1.3/1.4)    
-XX:MaxNewSize 年轻代最大值(for 1.3/1.4)    
-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:+DisableExplicitGC 关闭System.gc()   这个参数须要严格的测试
-XX:MaxTenuringThreshold 垃圾最大年龄   若是设置为0的话,则年轻代对象不通过Survivor区,直接进入年老代. 对于年老代比较多的应用,能够提升效率.若是将此值设置为一个较大值,则年轻代对象会在Survivor区进行屡次复制,这样能够增长对象再年轻代的存活 时间,增长在年轻代即被回收的几率
该参数只有在串行GC时才有效.
-XX:+AggressiveOpts 加快编译    
-XX:+UseBiasedLocking 锁机制的性能改善    
-Xnoclassgc 禁用垃圾回收    
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空闲空间中SoftReference的存活时间 1s softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap
-XX:PretenureSizeThreshold 对象超过多大是直接在旧生代分配 0 单位字节 新生代采用Parallel Scavenge GC时无效
另外一种直接在旧生代分配的状况是大的数组对象,且数组中无外部引用对象.
-XX:TLABWasteTargetPercent TLAB占eden区的百分比 1%  
-XX:+CollectGen0First FullGC时是否先YGC false  

GC性能方面的考虑算法

       对于GC的性能主要有2个方面的指标:吞吐量throughput(工做时间不算gc的时间占总的时间比)和暂停pause(gc发生时app对外显示的没法响应)。spring

1. Total Heap数组

       默认状况下,vm会增长/减小heap大小以维持free space在整个vm中占的比例,这个比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。缓存

通常而言,server端的app会有如下规则:并发

  • 对vm分配尽量多的memory;
  • 将Xms和Xmx设为同样的值。若是虚拟机启动时设置使用的内存比较小,这个时候又须要初始化不少对象,虚拟机就必须重复地增长内存。
  • 处理器核数增长,内存也跟着增大。

2. The Young Generationapp

       另一个对于app流畅性运行影响的因素是young generation的大小。young generation越大,minor collection越少;可是在固定heap size状况下,更大的young generation就意味着小的tenured generation,就意味着更多的major collection(major collection会引起minor collection)。框架

       NewRatio反映的是young和tenured generation的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,将这两个值设为同样就固定了young generation的大小(同Xms和Xmx设为同样)。

       若是但愿,SurvivorRatio也能够优化survivor的大小,不过这对于性能的影响不是很大。SurvivorRatio是eden和survior大小比例。

通常而言,server端的app会有如下规则:

  • 首先决定能分配给vm的最大的heap size,而后设定最佳的young generation的大小;
  • 若是heap size固定后,增长young generation的大小意味着减少tenured generation大小。让tenured generation在任什么时候候够大,可以容纳全部live的data(留10%-20%的空余)。

经验&&规则

  1. 年轻代大小选择
    • 响应时间优先的应用:尽量设大,直到接近系统的最低响应时间限制(根据实际状况选择).在此种状况下,年轻代收集发生的频率也是最小的.同时,减小到达年老代的对象.
    • 吞吐量优先的应用:尽量的设置大,可能到达Gbit的程度.由于对响应时间没有要求,垃圾收集能够并行进行,通常适合8CPU以上的应用.
    • 避免设置太小.当新生代设置太小时会致使:1.YGC次数更加频繁 2.可能致使YGC对象直接进入旧生代,若是此时旧生代满了,会触发FGC.
  2. 年老代大小选择
    1. 响应时间优先的应用:年老代使用并发收集器,因此其大小须要当心设置,通常要考虑并发会话率和会话持续时间等一些参数.若是堆设置小了,能够会形成内存碎 片,高回收频率以及应用暂停而使用传统的标记清除方式;若是堆大了,则须要较长的收集时间.最优化的方案,通常须要参考如下数据得到:
      并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
    2. 吞吐量优先的应用:通常吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.缘由是,这样能够尽量回收掉大部分短时间对象,减小中期的对象,而年老代尽存放长期存活对象.
  3. 较小堆引发的碎片问题
    由于年老代的并发收集器使用标记,清除算法,因此不会对堆进行压缩.当收集器回收时,他会把相邻的空间进行合并,这样能够分配给较大的对象.可是,当堆空间较小时,运行一段时间之后,就会出现"碎片",若是并发收集器找不到足够的空间,那么并发收集器将会中止,而后使用传统的标记,清除方式进行回收.若是出现"碎片",可能须要进行以下配置:
    -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩.
    -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的状况下,这里设置多少次Full GC后,对年老代进行压缩
  4. 用64位操做系统,Linux下64位的jdk比32位jdk要慢一些,可是吃得内存更多,吞吐量更大
  5. XMX和XMS设置同样大,MaxPermSize和MinPermSize设置同样大,这样能够减轻伸缩堆大小带来的压力
  6. 使用CMS的好处是用尽可能少的新生代,经验值是128M-256M, 而后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间很是的短,2G的内存, 大约20-80ms的应用程序停顿时间
  7. 系统停顿的时候多是GC的问题也多是程序的问题,多用jmap和jstack查看,或者killall -3 java,而后查看java控制台日志,能看出不少问题。(相关工具的使用方法将在后面的blog中介绍)
  8. 仔细了解本身的应用,若是用了缓存,那么年老代应该大一些,缓存的HashMap不该该无限制长,建议采用LRU算法的Map作缓存,LRUMap的最大长度也要根据实际状况设定。
  9. 采用并发回收时,年轻代小一点,年老代要大,由于年老大用的是并发回收,即便时间长点也不会影响其余程序继续运行,网站不会停顿
  10. JVM参数的设置(特别是 –Xmx –Xms –Xmn -XX:SurvivorRatio  -XX:MaxTenuringThreshold等参数的设置没有一个固定的公式,须要根据PV old区实际数据 YGC次数等多方面来衡量。为了不promotion faild可能会致使xmn设置偏小,也意味着YGC的次数会增多,处理并发访问的能力降低等问题。每一个参数的调整都须要通过详细的性能测试,才能找到特定应用的最佳配置。

     java.lang.StackOverflowError:(不多)
     java.lang.OutOfMemoryError:heap space(比较常见)
     java.lang.OutOfMemoryError: PermGen space (常常出现)

 java.lang.OutOfMemoryError: PermGen space 这个异常比较常见,是说JVM里的Perm内存区的异常溢出,因为JVM在默认的状况下,Perm默认为64M,而不少程序须要大量的Perm区内存,尤为使用到像spring等框架的时候,因为须要使用到动态生成类,而这些类不能被GC自动释放,因此致使OutOfMemoryError: PermGen space异常。解决方法很简单,增大JVM的 -XX:MaxPermSize 启动参数,就能够解决这个问题

 java.lang.OutOfMemoryError:heap space或 其它OutOfMemoryError,这个异常实际上跟上面的异常是一个异常,但解决方法不一样,因此分开来写。上面那个异常是由于JVM的perm区内存区分少了引发的(JVM的内存区分为 young,old,perm三种)。而这个异常是由于JVM堆内存或者说整体分少了。解决方法是更改 -Xms -Xmx 启动参数,一般是扩大1倍。xms是管理启动时最小内存量的,xmx是管里JVM最大的内存量的

StackOverflowError

在单线程操做中,不管是栈深度无限增长,仍是栈帧(每一个方法调用执行时都会在栈中建立一个栈帧,用来存储局部变量,操做数栈,动态链表,方法出口等信息)占的空间太大,都出现的是StackOverflowError

相关文章
相关标签/搜索