JVM GC算法与应用场景

If you have a single processor, single thread machine then you should use the serial collector (default for some configurations, can be enabled explicitly for with -XX:+UseSerialGC). 

For multiprocessor machines where your workload is basically CPU bound, use the parallel collector. This is enabled by default if you use the -server flag, or you can enable it explicitly with -XX:+UseParallelGC. 

用法:

select the parallel collector with -XX:+UseParallelGC and (optionally) enable parallel compaction with -XX:+UseParallelOldGC.New: parallel compaction is a feature introduced in J2SE 5.0 update 6 and enhanced in Java SE 6 that allows the parallel collector to perform major collections in parallel.Without parallel compaction, major collections are performed using a single thread, which can significantly limit scalability. Parallel compaction is enabled by adding the option -XX:+UseParallelOldGC to the command line.

If you'd rather keep the GC pauses shorter at the expense of using more total CPU time for GC, and you have more than one CPU, you can use the concurrent collector (-XX:+UseConcMarkSweepGC). Note that the concurrent collector tends to require more RAM allocated to the JVM than the serial or parallel collectors for a given workload because some memory fragmentation can occur. CMS is a good collector if avoiding GC jitters is of higher priority but if throughput is more important for eg for a batch like job the default SUN parallel collector does a better job.

如果你宁愿保持GC暂停在较短的时间,使用更多的总CPU时间进行GC的费用,和你有一个以上的CPU,可以使用并发收集器。要注意:比起serial 或者parallel 垃圾回收器,concurrent垃圾回收器需要给jvm分配更多的内存,对于一个给定的工作负载,因为一些内存碎片可能发生。concurrent回收器是为了避免GC抖动设计的不错的回收器。但是,如果吞吐量更GC抖动更重要(GC抖动,,顾名思义,就是GC导致jvm短暂不可提供服务),sun 的parallel做的更好

小助手:怎么知道设置了参数最终jvm采纳了哪些参数呢???因为jvm会更加操作系统,cpu,等对初始参数做调整

来看看java  -XX:+PrintFlagsFinal 命令

java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=68 -XX:+PrintGCDateStamps -XX:+PrintFlagsFinal java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=68 -XX:+PrintGCDateStamps -XX:+PrintFlagsFinal  |  grep -i "CMS"
     bool CMSAbortSemantics                         = false           {product}           
    uintx CMSAbortablePrecleanMinWorkPerIteration   = 100             {product}           
     intx CMSAbortablePrecleanWaitMillis            = 100             {manageable}        
    uintx CMSBitMapYieldQuantum                     = 10485760        {product}           
    uintx CMSBootstrapOccupancy                     = 50              {product}           
     bool CMSClassUnloadingEnabled                 := true            {product}           
    uintx CMSClassUnloadingMaxInterval              = 0               {product}           
     bool CMSCleanOnEnter                           = false           {product}           
     bool CMSCompactWhenClearAllSoftRefs            = true            {product}           
    uintx CMSConcMarkMultiple                       = 32              {product}           
     bool CMSConcurrentMTEnabled                    = true            {product}           
    uintx CMSCoordinatorYieldSleepCount             = 10              {product}           
     bool CMSDumpAtPromotionFailure                 = false           {product}           
    uintx CMSExpAvgFactor                           = 50              {product}           
     bool CMSExtrapolateSweep                       = false           {product}           
    uintx CMSFullGCsBeforeCompaction                = 0               {product}           
    uintx CMSIncrementalDutyCycle                   = 10              {product}           
    uintx CMSIncrementalDutyCycleMin                = 0               {product}           
     bool CMSIncrementalMode                        = false           {product}           
    uintx CMSIncrementalOffset                      = 0               {product}           
     bool CMSIncrementalPacing                      = true            {product}           
    uintx CMSIncrementalSafetyFactor                = 10              {product}           
    uintx CMSIndexedFreeListReplenish               = 4               {product}           
     intx CMSInitiatingOccupancyFraction           := 68              {product}           
     intx CMSInitiatingPermOccupancyFraction        = -1              {product}           
     intx CMSIsTooFullPercentage                    = 98              {product}           
   double CMSLargeCoalSurplusPercent                = 0.950000        {product}           
   double CMSLargeSplitSurplusPercent               = 1.000000        {product}           
     bool CMSLoopWarn                               = false           {product}           
    uintx CMSMaxAbortablePrecleanLoops              = 0               {product}           
     intx CMSMaxAbortablePrecleanTime               = 5000            {product}           
    uintx CMSOldPLABMax                             = 1024            {product}           
    uintx CMSOldPLABMin                             = 16              {product}           
    uintx CMSOldPLABNumRefills                      = 4               {product}           
    uintx CMSOldPLABReactivityCeiling               = 10              {product}           
    uintx CMSOldPLABReactivityFactor                = 2               {product}           
     bool CMSOldPLABResizeQuicker                   = false           {product}           
    uintx CMSOldPLABToleranceFactor                 = 4               {product}           
     bool CMSPLABRecordAlways                       = true            {product}           
    uintx CMSParPromoteBlocksToClaim                = 16              {product}           
     bool CMSParallelRemarkEnabled                  = true            {product}           
     bool CMSParallelSurvivorRemarkEnabled          = true            {product}           
     bool CMSPermGenPrecleaningEnabled              = true            {product}           
    uintx CMSPrecleanDenominator                    = 3               {product}           
    uintx CMSPrecleanIter                           = 3               {product}           
    uintx CMSPrecleanNumerator                      = 2               {product}           
     bool CMSPrecleanRefLists1                      = true            {product}           
     bool CMSPrecleanRefLists2                      = false           {product}           
     bool CMSPrecleanSurvivors1                     = false           {product}           
     bool CMSPrecleanSurvivors2                     = true            {product}           
    uintx CMSPrecleanThreshold                      = 1000            {product}           
     bool CMSPrecleaningEnabled                     = true            {product}           
     bool CMSPrintChunksInDump                      = false           {product}           
     bool CMSPrintObjectsInDump                     = false           {product}           
    uintx CMSRemarkVerifyVariant                    = 1               {product}           
     bool CMSReplenishIntermediate                  = true            {product}           
    uintx CMSRescanMultiple                         = 32              {product}           
    uintx CMSRevisitStackSize                       = 1048576         {product}           
    uintx CMSSamplingGrain                          = 16384           {product}           
     bool CMSScavengeBeforeRemark                   = false           {product}           
    uintx CMSScheduleRemarkEdenPenetration          = 50              {product}           
    uintx CMSScheduleRemarkEdenSizeThreshold        = 2097152         {product}           
    uintx CMSScheduleRemarkSamplingRatio            = 5               {product}           
   double CMSSmallCoalSurplusPercent                = 1.050000        {product}           
   double CMSSmallSplitSurplusPercent               = 1.100000        {product}           
     bool CMSSplitIndexedFreeListBlocks             = true            {product}           
     intx CMSTriggerPermRatio                       = 80              {product}           
     intx CMSTriggerRatio                           = 80              {product}           
     intx CMSWaitDuration                           = 2000            {manageable}        
    uintx CMSWorkQueueDrainThreshold                = 10              {product}           
     bool CMSYield                                  = true            {product}           
    uintx CMSYieldSleepCount                        = 0               {product}           
     intx CMSYoungGenPerWorker                      = 67108864        {pd product}        
    uintx CMS_FLSPadding                            = 1               {product}           
    uintx CMS_FLSWeight                             = 75              {product}           
    uintx CMS_SweepPadding                          = 1               {product}           
    uintx CMS_SweepTimerThresholdMillis             = 10              {product}           
    uintx CMS_SweepWeight                           = 75              {product}           
     bool PrintCMSInitiationStatistics              = false           {product}           
     intx PrintCMSStatistics                        = 0               {product}           
     bool UseCMSBestFit                             = true            {product}           
     bool UseCMSCollectionPassing                   = true            {product}           
     bool UseCMSCompactAtFullCollection             = true            {product}           
     bool UseCMSInitiatingOccupancyOnly            := true            {product}        

通过以上命令,,可以看到,,当使用  

java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=68 -XX:+PrintGCDateStamps  这些gc参数,,,jvm最终采纳了哪些参数,,因为参数太多,,数百个,,我只关心cms相关的参数,,,就grep 过滤下

其中 := 表示初始参数不是这样,,经过jvm自动优化过变成这样

项目实战:

公司的tcp服务,,跟手机app保持几万个长连接

最早的jvm参数

java -server -XX:+UseParallelGC -XX:MaxPermSize=256m -Xloggc:../logs/gc.log -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=../ -Xmx7168m -Xms7168m -Xmn3072m 

在该参数下,,每个1个半小时会执行一次fullgc,,,耗费时间大概1.8秒,,每隔1分钟执行一次YGC,耗费0.2秒,,,

在这种情况下,,服务器每1个半小时会停顿1.8秒(因为fullgc),,,这个是无法接受的,,,所以对gc参数做了优化

现在的jvm参数


-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=68 -XX:+PrintGCDateStamps

参数解释
CMSClassUnloadingEnabled  :
The standard Oracle/Sun VM look on the world is: Classes are forever. So once loaded, they stay in memory even if no one cares anymore. This usually is no problem since you don't have that many purely "setup" classes (= used once for setup and then never again). So even if they take up 1MB, who cares.

But lately, we have languages like Groovy, that define classes at runtime. Every time you run a script, one (or more) new classes are created and they stay in PermGen forever. If you're running a server, that means you have a memory leak.

If you enable CMSClassUnloadingEnabled the GC will sweep PermGen, too, and remove classes which are no longer used.

UseCMSInitiatingOccupancyOnly:如果新增非默认的参数,必须加上UseCMSInitiatingOccupancyOnly选项,这样保证,,从jvm启动到运行过程中一直遵守初始设置的参数(比如CMSInitiatingOccupancyFraction等参数才会一直保持生效),否则,jvm跑着跑着 就自动调节参数了

-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6

-XX:MaxTenuringThreshold=12:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行12次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论,当然会增加YGC的频率。

小助手2:HeapDumpBeforeFullGC 

在jvm启动参数加上HeapDumpBeforeFullGC一项,,,,可以在fullgc前将heap dump出来,方便分析问题

java -XX:+PrintFlagsFinal |grep -i "before"
    uintx CMSFullGCsBeforeCompaction                = 0               {product}           
     bool CMSScavengeBeforeRemark                   = false           {product}           
     bool HeapDumpBeforeFullGC                      = false           {manageable}        
     bool PrintClassHistogramBeforeFullGC           = false           {manageable}        
     intx SafepointSpinBeforeYield                  = 2000            {product}           
     bool ScavengeBeforeFullGC                      = true            {product}     

该参数说明,该参数可以动态修改(就是在不需要重启jvm情况下修改,当然前提是,,必须激活JMX)

动态激活该参数命令


$ jps  
15920 Launcher  
$ jinfo -flag +HeapDumpBeforeFullGC 15920 

如果FullGC的频率有点高怎么办?

将对象提前释放掉,在younggc阶段就把内存释放掉。除了程序中控制对象释放时间外,还有个办法是调整jvm启动参数。

1 适当增加survivor区的大小,,这样会延缓survivor之间拷贝的时间,,,经过MaxTenuringThreshold次拷贝后,,才把live 对象copy到老生代。ygc的过程:如果 eden满了,,会触发一次gc,将eden已经survivor里面不可达的对象释放掉,,并将eden里面live对象拷贝到survivor里面

参考

sun公司的官方对于垃圾回收算法的指导

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generation_sizing.young_gen.survivors

http://www.myexception.cn/program/1059582.html

什麼時候觸發young gc

http://stackoverflow.com/questions/13660871/jvm-garbage-collection-in-young-generation

gc原理

http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots.html

http://www.cubrid.org/blog/dev-platform/the-principles-of-java-application-performance-tuning/
————————————————
版权声明:本文为CSDN博主「艾比aibi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aibisoft/article/details/21123249

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值