JAVA全面了解GC调优

有必要优化GC吗?

确切的说是 基于Java的应用一定需要进行GC优化吗?我认为并非所有基于Java的应用都需要进行GC优化,例如基于Java的系统有如下参数或行为:

  • 已经通过-Xms 和 -Xmx 指定了内存大小
  • 包含了 -server 参数
  • 系统中未出现 超时 等日志

换句话说,如果你没有设置内存大小而且出现了大量超时日志,那么你需要在系统中进行GC优化了。 

但是有件事要铭记于心:GC优化是你最后的手段。

思考下GC优化的根本原因:Java中创建的对象由垃圾收集器来清理,同时待清理对象的数量和各类GC的执行次数又和创建对象总数量成正比。因此,为了控制GC的执行,首先要做的是 减少创建对象的总数量

俗话说,”积少成多”。我们需要关注一些小事情,否则”养成气候”之后将难以驾驭。例如:

  • 使用StringBuilder或StringBuffer代替String
  • 尽可能少的输出日志

如果在几次参数调整后内存使用情况有所改善,你就可以进行GC优化了。我将GC优化的目的分成两类:

  • 将转移到老年代的对象数量降到最少
  • 减少Full GC的执行时间(减少stop the word发生次数)

 

将转移到老年代的对象数量降到最少

Oracle JVM提供了分代垃圾回收机制(JDK1.7及以上的G1 GC除外)。换句话说,对象创建在Eden区,然后在Survivor的From和To区之间移动,最后存活的对象被转移到老年代。一些大对象在Eden区创建之后被直接转移到老年代。相对新生代,老年代的GC消耗的时间更长。因此,减少从新生代转移到老年代的对象数量可以降低Full GC的频率。

 减少从新生代转移到老年代对象的数量的说法容易造成误解,而且也不可能,但可以通过 调整年轻代的大小 来实现。

减少Full GC的时间

和Minor GC相比,Full GC的执行时间长很多。因此,如果执行Full GC的时间过长(超过1s),将导致连接服务的请求超时。

如果通过减少老年代的大小来降低Full GC执行时间,会造成OutOfMemoryError或增加Full GC的次数

如果老年代设置过小,就会频繁触发full gc,full gc是非常耗时的。年轻代在经过n(hotspot默认是15)轮后会进入老年代,这样老年代顶不住了,就会触发full gc,回收时需要stop the world,这样系统经常发生长时间停顿,影响系统的吞吐量。

如果增大老年代大小以期减少Full GC的执行次数,那么执行时间又会增加

因此,需要合理的设置 老年代大小。

stop-the-world事件耗时很长

不合适的GC选项可能导致stop-the-world时间过长,你可以通过分析器或heap dump来定位问题。

这意味着你可以在检查堆中对象类型和数量后判断原因。如果你发现很多不必要的对象,你最好修改源码,如果创建对象过程中没有什么特别的问题,最好直接变更GC参数。

影响GC性能的参数

不要去想 “有人在使用一些GC参数后性能显著提升,为什么我们不使用相同的参数?“,原因是 不同Web应用中对象的大小和生命周期不同。

对于Java GC参数的设置,设置多个参数并不会提高GC的执行速度,恰恰相反,可能会降低执行速度。GC优化的基本原则是:将不同的GC参数应用到2个或多个主机,然后比对结果,最后将性能最优的参数组合推广到其他主机,这点必须铭记于心。

下表是一些影响GC性能的参数。

表1: GC优化时需要检查的JVM参数

分类 参数 描述

堆区  -Xms 启动JVM时的初始堆大小

         -Xmx 最大堆内存

新生代  -XX:NewRatio 新生代和老年代内存大小比例

             -XX:NewSize 新生代大小

             -XX:SurvivorRatio Eden和Survivor区的比率

 

我经常使用 -Xms、-Xmx、-XX:NewRatio 三个参数来进行GC调优。-Xms、-Xmx 是肯定需要的,-XX:NewRatio 的设置将会显著的影响GC性能。

有的人可能会问 如何设置Perm区大小? 你可以通过 -XX:PermSize、-XX:MaxPermSize 设置,这个会与Perm区 OutOfMemoryError相关。

另一个会影响GC性能的是 GC类型,下面是基于JDK1.6可选的GC类型:

类别   参数   备注

Serial GC                         -XX:+UseSerialGC

Parallel GC                      -XX:+UseParallelGC

                                        -XX:ParallelGCThreads=value

Parallel Compacting GC  -XX:+UseParallelOldGC

CMS GC                          -XX:+UseConcMarkSweepGC

                                        -XX:+UseParNewGC

                                        -XX:+CMSParallelRemarkEnabled

                                        -XX:CMSInitiatingOccupancyFraction=value

                                        -XX:+UseCMSInitiatingOccupancyOnly

G1                                   -XX:+UnlockExperimentalVMOptions

                                        -XX:+UseG1GC 在JDK6,这两个参数必须同时使用

除G1 GC外,GC类型可以通过第一行的参数来切换。最常见的GC类型是 Servial GC,它针对客户端系统专门进行了优化。

影响GC性能的参数有很多,但是上面的参数有着最为显著的影响。记住,设置过多的参数并不能保证一定会缩短GC的时间。

参考:https://chenyongjun.vip/articles/56

转载于:https://my.oschina.net/u/3687664/blog/3005558

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值