JVM 调优

jopen 8年前

JVM 堆内存分区

堆:年轻代,老年代,持久代

年轻代:Eden,Survivor1,Survivor2

一个性能较好的jvm参数配置以及jvm的简介

JVM基本回收算法

  1. 引用计数(Reference Counting
    比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。

  2. 标记-清除(Mark-Sweep
    此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。

  3. 复制(Copying
    此 算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理 正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不过出现碎片问题。当然,此算法的缺点也是很明显的,就是需要两倍 内存空间。

  4. 标记-整理(Mark-Compact
    此算法结 合了标记-清除复制两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活 对象压缩到堆的其中一块,按顺序排放。此算法避免了标记-清除的碎片问题,同时也避免了复制算法的空间问题。

  5. 增量收集(Incremental Collecting)
    实施垃圾回收算法,即:在应用进行的同时进行垃圾回收。不知道什么原因JDK5.0中的收集器没有使用这种算法的。

  6. 分代(Generational Collecting
    基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。


JVM常见配置汇总

  1. 堆设置

    • -Xms:初始堆大小(默认值,物理内存的1/64)

    • -Xmx:最大堆大小(默认值,物理内存的1/4)

    • -Xmn:年轻代大小(Sun官方推荐年轻代配置为整个堆的3/8)

    • -XX:NewSize=n:设置年轻代大小

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

    • -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4。

    • -XX:PermSize=n:设置持久代的大小 (物理内存的1/64)

    • -XX:MaxPermSize=n:设置持久代大小最大值(物理内存的1/4)

    • -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

    • -Xss:每个线程的堆栈大小,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.

    • -XX:+UseBiasedLocking:锁机制性能改善


  2. 收集器设置

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

    • -XX:+UseParallelGC:设置并行收集器 此配置仅对年轻代有效

    • -XX:+UseParalledlOldGC:设置并行年老代收集器

    • -XX:+UseConcMarkSweepGC:设置并发收集器(参数表示对于老年代的回收采用CMS。CMS采用的基础算法是:标记—清除。)

    • -XX:ParallelGCThreads=n:设置并行收集器线程数,此值最好与处理器核数相同

    • -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间(每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值.)

    • XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

  3. 垃圾回收统计信息

    • -XX:+PrintGC

    • -XX:+PrintGCDetails

    • -XX:+PrintGCTimeStamps

    • -Xloggc:filename

  4. 并发收集器设置

    • -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。

    • -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。


常见配置:

请看一下一个时间的Java参数配置:(服务器:Linux 64Bit,8Core×16G) 

 JAVA_OPTS="$JAVA_OPTS -server -Xms3G -Xmx3G -Xss256k 

          -XX:PermSize=128m 

          -XX:MaxPermSize=128m 

          -XX:+UseParallelOldGC 

          -XX:+HeapDumpOnOutOfMemoryError 

          -XX:HeapDumpPath=/usr/aaa/dump 

          -XX:+PrintGCDetails 

          -XX:+PrintGCTimeStamps 

          -Xloggc:/usr/aaa/dump/heap_trace.txt 

          -XX:NewSize=1G 

          -XX:MaxNewSize=1G"


调优总结

  1. 年轻代大小选择

    • 响应时间优先的应用尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。

    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。

  2. 年老代大小选择

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

      • 并发垃圾收集信息

      • 持久代并发收集次数

      • 传统GC信息

      • 花在年轻代和年老代回收上的时间比例

    • 减少年轻代和年老代花费的时间,一般会提高应用的效率

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

    • CMS调优可针对老年代

  3. 较小堆引起的碎片问题

       因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行                合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集                器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可                能需要进行如下配置:

    • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。

    • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩


    一个性能较好的web服务器jvm参数配置:

    -server//服务器模式

-Xmx2g   //JVM最大允许分配的堆内存,按需分配
        -Xms2g   //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存。
        -Xmn256m   //年轻代内存大小,整个JVM内存=年轻代 + 年老代 + 持久代
        -XX:PermSize=128m   //持久代内存大小
        -Xss256k   //设置每个线程的堆栈大小
        -XX:+DisableExplicitGC   //忽略手动调用GC, System.gc()的调用就会变成一个空调用,完全不触发GC
        -XX:+UseConcMarkSweepGC  //并发标记清除(CMS)收集器
        -XX:+CMSParallelRemarkEnabled   //降低标记停顿
        -XX:+UseCMSCompactAtFullCollection   //在FULL GC的时候对年老代的压缩
       -XX:LargePageSizeInBytes=128m   //内存页的大小
        -XX:+UseFastAccessorMethods   //原始类型的快速优化
        -XX:+UseCMSInitiatingOccupancyOnly //使用手动定义初始化定义开始CMS收集
        -XX:CMSInitiatingOccupancyFraction=70 //使用cms作为垃圾回收使用70%后开始CMS收集



来自: http://my.oschina.net/manmao/blog/601933