`
wusuoya
  • 浏览: 629764 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

介绍并调优JVM GC(Garbage Collection)

    博客分类:
  • Java
 
阅读更多

下文是转贴于http://www.javadby.com/yuyanjichu/20080322/5220.html。因为这几天压力测试,然后再重温GC的时候,觉得这片文章写得比较详细,对于去看GC print有一些帮助。转贴一下。

 

调整JVM GC(Garbage Collection),可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程,由于各个程序具备不同的特点,如:web和GUI程序就有很大区别(Web可以适当的停顿,但GUI停顿是客户无法接受的),而且由于跑在各个机器上的配置不同(主要cup个数,内存不同),所以使用的GC种类也会不同。接下来,我简单介绍一下如何调整GC。

     首先说一下如何监视GC,你可以使用我以前文章中提到的JDK中的jstat工具 ,也可以在java程序启动的opt里加上如下几个参数(注:这两个参数只针对SUN的HotSpot VM):

    -XX:-PrintGC     Print messages at garbage collection. Manageable.
    -XX:-PrintGC Details     Print more details at garbage collection. Manageable. (Introduced in 1.4.0.)
    -XX:-PrintGCTimeStamps     Print timestamps at garbage collection. Manageable (Introduced in 1.4.0.)

   当把-XX:-PrintGC Details 加入到java opt里以后可以看见如下输出:

    [GC [DefNew: 34538K->2311K(36352K), 0.0232439 secs] 45898K->15874K(520320K), 0.0233874 secs]
    [Full GC [Tenured: 13563K->15402K(483968K), 0.2368177 secs] 21163K->15402K(520320K), [Perm : 28671K->28635K(28672K)], 0.2371537 secs]

    他们分别显示了GC的过程,清理出了多少空间。第一行GC使用的是 ‘普通GC’(Minor Collections),第二行使用的是 ‘全GC’(Major Collections)。他们的区别很大,在第一行最后我们可以看见他的时间是0.0233874秒,而第二行的Full GC的时间是0.2371537秒。第二行的时间是第一行的接近10倍,也就是我们这次调优的重点,减少Full GC 的次数,以为Full GC 会暂停程序比较长的时间,如果Full GC 的次数比较多。程序就会经常性的假死。当然这只是他们的表面现象,接下来我仔细介绍一下GC,和 Full GC(为后面的调优做准备)。

      我们知道Java和C++的区别主要是,Java不需要像c++那样,由程序员主动的释放内存。而是由JVM里的GC(Garbage Collection)来,在适当的时候替我们释放内存。GC 的内部工作,即GC的算法有很多种, 如:标记清除收集器,压缩收集器,分代收集器等等。现在比较常用的是分代收集(也是SUN VM使用的),即将内存分为几个区域,将不同生命周期的对象放在不同区域里(新的对象会先 生成在Young area,在几次GC以后,如过没有收集到,就会逐渐升级到Tenured area)。在GC收集的时候,频繁收集生命周期短的区域(Young area),因为这个区域内的对象生命周期比较短,GC 效率也会比较高。而比较少的收集生命周期比较长的区域(Old area or Tenured area),以及基本不收集的永久区(Perm area)。
     注:Young area又分为三个区域分别叫Eden,和俩个Survivor spaces。Eden用来存放新的对象,Survivor spaces用于 新对象 升级到 Tenured area时的 拷贝。
     我们管收集 生命周期短的区域(Young area) 的收集叫 GC,而管收集 生命周期比较长的区域(Old area or Tenured area)的收集叫 Full GC,因为他们的收集算法不同,所以使用的时间也会不同。我们要尽量减少 Full GC 的次数。

      接下来介绍一下 HotSpot VM GC 的种类,GC在 HotSpot VM 5.0里有四种。一种是默认的叫 serial collector,另外几种分别叫throughput collector,concurrent low pause collector, incremental (sometimes called train) low pause collector(废弃掉了)。以下是SUN的官方说明:  

   1. The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.
   2. The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.
   3. The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.

       简单来说就是throughput collector和concurrent low pause collector:使用多线程的方式,利用多CUP来提高GC的效率,而throughput collector与concurrent low pause collector的去别是throughput collector只在young area使用使用多线程,而concurrent low pause collector则在tenured generation也使用多线程。

        根据官方文档,他们俩个需要在多CPU的情况下,才能发挥作用。在一个CPU的情况下,会不如默认的serial collector,因为线程管理需要耗费CPU资源。而在两个CPU的情况下,也挺高不大。只是在更多CPU的情况下,才会有所提高。当然 concurrent low pause collector有一种模式可以在CPU较少的机器上,提供尽可能少的停顿的模式,见下文。

        当要使用throughput collector时,在java opt里加上-XX:+UseParallelGC,启动throughput collector收集。也可加上-XX:ParallelGCThreads=<desired number>来改变线程数。还有两个参数 -XX:MaxGCPauseMillis=<nnn>和 -XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用来控制最大暂停时间,而-XX: GCTimeRatio可以提高GC说占CPU的比,以最大话的减小heap。

      当要使用 concurrent low pause collector时,在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector还有一种为CPU少的机器准备的模式,叫Incremental mode。这种模式使用一个CPU来在程序运行的过程中GC,只用很少的时间暂停程序,检查对象存活。

        在Incremental mode里,每个收集过程中,会暂停两次,第二次略长。第一次用来,简单从root查询存活对象。第二次用来,详细检查存活对象。整个过程如下:  

    * stop all application threads; do the initial mark; resume all application threads(第一次暂停,初始话标记)
    * do the concurrent mark (uses one procesor for the concurrent work)(运行是标记)
    * do the concurrent pre-clean (uses one processor for the concurrent work)(准备清理)
    * stop all application threads; do the remark; resume all application threads(第二次暂停,标记,检查)
    * do the concurrent sweep (uses one processor for the concurrent work)(运行过程中清理)
    * do the concurrent reset (uses one processor for the concurrent work)(复原)

       当要使用Incremental mode时,需要使用以下几个变量:
       -XX:+CMSIncrementalMode default: disabled 启动i-CMS模式(must with -

XX:+UseConcMarkSweepGC)
       -XX:+CMSIncrementalPacing default: disabled 提供自动校正功能
       -XX:CMSIncrementalDutyCycle=<N> default: 50 启动CMS的上线
       -XX:CMSIncrementalDutyCycleMin=<N> default: 10 启动CMS的下线
       -XX:CMSIncrementalSafetyFactor=<N> default: 10 用来计算循环次数
       -XX:CMSIncrementalOffset=<N> default: 0 最小循环次数(This is the percentage (0-

100) by which the incremental mode duty cycle is shifted to the right within the period 

between minor collections.)
       -XX:CMSExpAvgFactor=<N> default: 25 提供一个指导收集数

      SUN推荐的使用参数是:

        -XX:+UseConcMarkSweepGC /
        -XX:+CMSIncrementalMode /
        -XX:+CMSIncrementalPacing /
        -XX:CMSIncrementalDutyCycleMin=0 /
        -XX:CMSIncrementalDutyCycle=10 /
        -XX:+PrintGC Details /
        -XX:+PrintGCTimeStamps /
        -XX:-TraceClassUnloading

       注:如果使用throughput collector和concurrent low pause collector,这两种垃圾收集器,需要适当的挺高内存大小,以为多线程做准备。下文是转贴于http://www.javadby.com/yuyanjichu/20080322/5220.html。因为这几天压力测试,然后再重温GC的时候,觉得这片文章写得比较详细,对于去看GC print有一些帮助。转贴一下。

 

调整JVM GC(Garbage Collection),可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程,由于各个程序具备不同的特点,如:web和GUI程序就有很大区别(Web可以适当的停顿,但GUI停顿是客户无法接受的),而且由于跑在各个机器上的配置不同(主要cup个数,内存不同),所以使用的GC种类也会不同。接下来,我简单介绍一下如何调整GC。

     首先说一下如何监视GC,你可以使用我以前文章中提到的JDK中的jstat工具 ,也可以在java程序启动的opt里加上如下几个参数(注:这两个参数只针对SUN的HotSpot VM):

    -XX:-PrintGC     Print messages at garbage collection. Manageable.
    -XX:-PrintGC Details     Print more details at garbage collection. Manageable. (Introduced in 1.4.0.)
    -XX:-PrintGCTimeStamps     Print timestamps at garbage collection. Manageable (Introduced in 1.4.0.)

   当把-XX:-PrintGC Details 加入到java opt里以后可以看见如下输出:

    [GC [DefNew: 34538K->2311K(36352K), 0.0232439 secs] 45898K->15874K(520320K), 0.0233874 secs]
    [Full GC [Tenured: 13563K->15402K(483968K), 0.2368177 secs] 21163K->15402K(520320K), [Perm : 28671K->28635K(28672K)], 0.2371537 secs]

    他们分别显示了GC的过程,清理出了多少空间。第一行GC使用的是 ‘普通GC’(Minor Collections),第二行使用的是 ‘全GC’(Major Collections)。他们的区别很大,在第一行最后我们可以看见他的时间是0.0233874秒,而第二行的Full GC的时间是0.2371537秒。第二行的时间是第一行的接近10倍,也就是我们这次调优的重点,减少Full GC 的次数,以为Full GC 会暂停程序比较长的时间,如果Full GC 的次数比较多。程序就会经常性的假死。当然这只是他们的表面现象,接下来我仔细介绍一下GC,和 Full GC(为后面的调优做准备)。

      我们知道Java和C++的区别主要是,Java不需要像c++那样,由程序员主动的释放内存。而是由JVM里的GC(Garbage Collection)来,在适当的时候替我们释放内存。GC 的内部工作,即GC的算法有很多种, 如:标记清除收集器,压缩收集器,分代收集器等等。现在比较常用的是分代收集(也是SUN VM使用的),即将内存分为几个区域,将不同生命周期的对象放在不同区域里(新的对象会先 生成在Young area,在几次GC以后,如过没有收集到,就会逐渐升级到Tenured area)。在GC收集的时候,频繁收集生命周期短的区域(Young area),因为这个区域内的对象生命周期比较短,GC 效率也会比较高。而比较少的收集生命周期比较长的区域(Old area or Tenured area),以及基本不收集的永久区(Perm area)。
     注:Young area又分为三个区域分别叫Eden,和俩个Survivor spaces。Eden用来存放新的对象,Survivor spaces用于 新对象 升级到 Tenured area时的 拷贝。
     我们管收集 生命周期短的区域(Young area) 的收集叫 GC,而管收集 生命周期比较长的区域(Old area or Tenured area)的收集叫 Full GC,因为他们的收集算法不同,所以使用的时间也会不同。我们要尽量减少 Full GC 的次数。

      接下来介绍一下 HotSpot VM GC 的种类,GC在 HotSpot VM 5.0里有四种。一种是默认的叫 serial collector,另外几种分别叫throughput collector,concurrent low pause collector, incremental (sometimes called train) low pause collector(废弃掉了)。以下是SUN的官方说明:  

   1. The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.
   2. The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.
   3. The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.

       简单来说就是throughput collector和concurrent low pause collector:使用多线程的方式,利用多CUP来提高GC的效率,而throughput collector与concurrent low pause collector的去别是throughput collector只在young area使用使用多线程,而concurrent low pause collector则在tenured generation也使用多线程。

        根据官方文档,他们俩个需要在多CPU的情况下,才能发挥作用。在一个CPU的情况下,会不如默认的serial collector,因为线程管理需要耗费CPU资源。而在两个CPU的情况下,也挺高不大。只是在更多CPU的情况下,才会有所提高。当然 concurrent low pause collector有一种模式可以在CPU较少的机器上,提供尽可能少的停顿的模式,见下文。

        当要使用throughput collector时,在java opt里加上-XX:+UseParallelGC,启动throughput collector收集。也可加上-XX:ParallelGCThreads=<desired number>来改变线程数。还有两个参数 -XX:MaxGCPauseMillis=<nnn>和 -XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用来控制最大暂停时间,而-XX: GCTimeRatio可以提高GC说占CPU的比,以最大话的减小heap。

      当要使用 concurrent low pause collector时,在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector还有一种为CPU少的机器准备的模式,叫Incremental mode。这种模式使用一个CPU来在程序运行的过程中GC,只用很少的时间暂停程序,检查对象存活。

        在Incremental mode里,每个收集过程中,会暂停两次,第二次略长。第一次用来,简单从root查询存活对象。第二次用来,详细检查存活对象。整个过程如下:  

    * stop all application threads; do the initial mark; resume all application threads(第一次暂停,初始话标记)
    * do the concurrent mark (uses one procesor for the concurrent work)(运行是标记)
    * do the concurrent pre-clean (uses one processor for the concurrent work)(准备清理)
    * stop all application threads; do the remark; resume all application threads(第二次暂停,标记,检查)
    * do the concurrent sweep (uses one processor for the concurrent work)(运行过程中清理)
    * do the concurrent reset (uses one processor for the concurrent work)(复原)

       当要使用Incremental mode时,需要使用以下几个变量:
       -XX:+CMSIncrementalMode default: disabled 启动i-CMS模式(must with -

XX:+UseConcMarkSweepGC)
       -XX:+CMSIncrementalPacing default: disabled 提供自动校正功能
       -XX:CMSIncrementalDutyCycle=<N> default: 50 启动CMS的上线
       -XX:CMSIncrementalDutyCycleMin=<N> default: 10 启动CMS的下线
       -XX:CMSIncrementalSafetyFactor=<N> default: 10 用来计算循环次数
       -XX:CMSIncrementalOffset=<N> default: 0 最小循环次数(This is the percentage (0-

100) by which the incremental mode duty cycle is shifted to the right within the period 

between minor collections.)
       -XX:CMSExpAvgFactor=<N> default: 25 提供一个指导收集数

      SUN推荐的使用参数是:

        -XX:+UseConcMarkSweepGC /
        -XX:+CMSIncrementalMode /
        -XX:+CMSIncrementalPacing /
        -XX:CMSIncrementalDutyCycleMin=0 /
        -XX:CMSIncrementalDutyCycle=10 /
        -XX:+PrintGC Details /
        -XX:+PrintGCTimeStamps /
        -XX:-TraceClassUnloading

       注:如果使用throughput collector和concurrent low pause collector,这两种垃圾收集器,需要适当的挺高内存大小,以为多线程做准备。

分享到:
评论

相关推荐

    The-Java-Garbage-Collection-Mini-book.zip

    InfoQ的关于JVM GC的学习资料,对于深入学习JVM的GC机制很有帮助

    The Java Garbage Collection Mini Book

    InfoQ的关于JVM GC的学习资料,对于深入学习JVM的GC机制很有帮助

    Understanding Java Garbage Collection

    Java垃圾回收机制的工作原理,不同JVM使用的GC算法分析

    Java Garbage Collection 与各种GC算法.zip

    它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)...

    初步理解:jvm运行机制,java程序运行机制,堆栈详解,jvm调优的目的。

    谷咕咕最近在准备面试,本来想多看看堆和栈的关系,看看发现又设计到gc(Garbage Collection)垃圾回收机制,发现盲区太多了,就去粗略的学习了一下jvm(java虚拟机),发现之前只会写程序,底层的东西真是太丰富了...

    Memory Efficient Hard Real-Time Garbage Collection by Tobias Ritzau.pdf

    Building Memory-efficient Java Applications: Practices and Challenges Nick Mitchell, Gary Sevitsky (presenting) IBM TJ Watson Research Center Hawthorne, NY USA ...ACM SIGPLAN PLDI 2009, Dublin, Ireland

    详细介绍Java垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再...

    JAVA垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再...

    jvm垃圾回收思维导图

    圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。该思维导图完整的描述了垃圾回收的各个关键点

    JVM参数设置详细说明

    后来我们就用CMS gc(-XX:+UseConcMarkSweepGC),当时的总heap还是3g,新生代1.5g后,观察不是很理想,改为jvm heap为2g新生代设置-Xmn1g,在这样的情况下young gc发生的频率变成7、8秒一次,平均每次时间40-50毫秒...

    Java.Interview.Bootcamp

    Title: Java Interview Bootcamp Author: Sam Atkinson Length: 106 pages Edition: 1 Language: English Publication Date: 2015-02-...10 JVM and Garbage Collection 11 Threading 12 Big O Notation 13 Conclusion

    JAVA虚拟机原理

    JavaGC(GarbageCollection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码。在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该...

    eclipse 内存溢出解决办法

    Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP 会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。 ...

    【JVM和性能优化】2.垃圾回收器和内存分配策略

    文章目录内存回收引用计数法可达性分析浅谈引用强引用软引用弱引用虚引用方法区GC 算法标记-清除算法(Mark-Sweep)复制算法(Copying)标记-整理算法(Mark...为什么要了解GC(Garbage Collection)和内存分配策略 1、面

    java垃圾回收知识全集

    Java 垃圾回收(Garbage Collection,简称 GC)是现代编程语言中的重要特性,为开发人员提供了自动化内存管理的能力。它通过自动识别和回收不再使用的内存,减轻了程序员手动释放内存的负担,提高了应用程序的稳定性...

    优化Java垃圾收集器改进系统性能

    当系统的处理能力有某种变化趋势时,除了关于等待队列、执行线程,EJB池以及数据库连接池和StatementCache方面的调优外,还要考虑到Java垃圾收集器(GarbageCollection,本文简称GC)对系统性能的影响。本文介绍了...

    Smart-Stealing-for-Parallel-GC-in-JVM:智能窃取

    如果您认为这项工作对您有用,请引用我们的工作: 乳胶: @inproceedings{qian2015smartstealing, title={SmartStealing: Analysis and Optimization of Work Stealing in Parallel Garbage Collection for Java VM...

Global site tag (gtag.js) - Google Analytics