jvm性能调优理论

1. 关于jvm使用的回收机制
分代回收
将整个堆分为New(年轻代), Tenured(年老代), PermGen(永久代)
其中"年轻代"又分为Eden Space和Survivor1, Survivor2 Space
2. 大概过程
所有新生成的对象存放于Eden Space中,当Eden满无法继续存放时,会进行一次Scavenge
GC(包含清除Eden及整理Survivors space),清除Eden中无用的对象(unreachable),并将尚且存活的对象(reachable)复制到survivor中的正放置对象的那个space,如果此时该space不够空间进行放置,则也会进行一次回收处理,销毁不再使用的对象(释放空间),并且将幸存的对象复制到另外一个空着的survivor space中,且将从Eden中幸存的对象一并放入,注意此时尚有另一机制,该机制会依据jvm参数中设置的次数决定survivor中的对象在survivor两空间中来回复制了多少次后需要被复制到Tenured中,这样保证了生命周期较长对象筛选的严格性(只有经过层层筛选,确实为一个生命周期较长的对象才会被放入"年老代",因为一旦进入年老代,被回收的几率相对于"年轻代"来说就低很多);一旦Tenured中空间不足,则会触发一次Full GC(尽量减少Full GC次数,Full GC会对整个堆进行一次整理,包括New, Tenured, PermGen),对整个堆进行一次整理,销毁无用的对象,释放空间。PermGen也一样,当PermGen满时,会触发一次Full GC,其中PermGen中可能会卸载一些不用的class等元数据。
3. 回收依据算法
    a. 引用计数法
        每次引用该对象与结束引用都会对该对象被引用的数目进行计数,计数为0则作为被回收的依据。
    b. 对象引用遍历
        从最顶端的一组根对象出发,沿着整个对象图上的每条链接,递归确定可到达的对象,如果某个对象不能从这些根结点中的一个到达,则将它作为垃圾回收。(这个过程分为两个步骤:标记+清除---mark+sweep)
4. 调优建议
   a. 尽量将-Xms与-Xmx设为相同,避免内存进行收缩,减小开销。
   b. 对于web服务器项目,多核cpu时使用-XX:+UseParallelGC并行垃圾回收算法,该算法强调吞吐量优先。而并发垃圾回收算法强调的是即时性,垃圾回收时,程序同时运行,适合GUI程序。
   c. 尽量减少Full GC的次数(Full GC时间较长,会让客户请求阻塞),所以程序中避免调用System.gc(),会导致Full GC;
   d. 解释: -XX:NewRatio=4代表年老代与New(年轻代)的比率, Tenured:New=4:1
           -XX:SurvivorRatio=4, Eden:Survivor=4:1, 因为有两个Survivor,所以一个survivor占New空间的1/6;
   e. -XX:ParallelGCThreads=8:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等
   f. -Xmn2g:设置年轻代大小为2G。整个堆内存大小 = 年轻代大小 + 年老代大小。所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
   g. -XX:PermSize=256M:设置堆内存持久代 初始值为256M
      -XX:MaxPermSize=512M:设置持久代最大值为512M
     上两项可以设置为一致,避免收缩开销,大小可以设置为峰值大小,外加预留1/3空间
   h. 调优时权衡gc的次数以及每次gc的时间
   i. 年轻代大小选择
    * 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
    * 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
      
      年老代大小选择
    * 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:
          o 并发垃圾收集信息
          o 持久代并发收集次数
          o 传统GC信息
          o 花在年轻代和年老代回收上的时间比例
      减少年轻代和年老代花费的时间,一般会提高应用的效率
    * 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

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

    * -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    * -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
   j. 目标参考: Scavenge GC耗时在10-40ms左右,不应超过300-400ms, Full GC基本不发生(很长时间发生一次),若JVM开启了JMX的话, JMX将会1小时执行一次Full GC以清除引用;

5. 使用jdk自带的工具jconsole配合服务器开启jmx进行观察
    如果遇到内存泄漏,要用jstack和jmap、jstat等多看看,应该可以找到问题
    refer to:http://hi.baidu.com/camaro/blog/item/384b31e9e7bae237b90e2d44.html

6. 基本回收算法

   a. 引用计数(Reference Counting)
      比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。
   b. 标记-清除(Mark-Sweep)
      此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。
   c. 复制(Copying)
      此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不过出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。
   d. 标记-整理(Mark-Compact)
      此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。
   e. 增量收集(Incremental Collecting)
      实施垃圾回收算法,即:在应用进行的同时进行垃圾回收。不知道什么原因JDK5.0中的收集器没有使用这种算法的。
   f. 分代(Generational Collecting)
      基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个, 年轻代一般选择"复制",年老代一般选择"标记-清除")进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。



附:
jvm has 3 segments in memory
1. Stack Segment
2. Heap Segment
3. Code Segment
Static members (variables or methods) reside in the Code Segment of the memory.





refer to:
    1. http://blog.csdn.net/kthq/archive/2010/01/11/5180962.aspx
    2. http://dev.firnow.com/course/3_program/java/javajs/20090823/169934.html
    3. http://hxraid.iteye.com/blog/745113
    4. http://unixboy.iteye.com/blog/174173
    5. http://java.sun.com/performance/reference/whitepapers/tuning.html
    6. http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning
    7. http://hi.baidu.com/jchiel/blog/item/bc1f4f17d4f353064b90a739.html
    8. http://blog.csdn.net/chen77716/archive/2010/06/26/5695893.aspx
    9. http://zhdy.iteye.com/blog/343911







你可能感兴趣的:(jvm,oracle,应用服务器,算法,Blog)