性能调优需要掌握的gc知识
fullgc频繁,考虑老年代内存是否太小
YoungGc频繁,考虑年轻代内存是否太小
YoungGc时间过长,程序中出现了大对象, 增加 -XX:PretenureSizeThreshold,这个值的意思是超过这个值的时候,对象直接在old区分配内存,默认值是0,意思是不管多大都是先在eden中分配内存
自动垃圾回收机制,简单来说就是寻找 Java堆中的无用对象。打个比方:你的房间是JVM的内存,你在房间里看书学习(处理请求),但你同时在制造垃圾和脏乱,而你妈就是 GC,负责打扫你房间的垃圾,试想一下,你妈进来回收垃圾的时候(发生gc),势必会打扰到你的学习(无法处理请求),但是如果你妈不来打扫,你房间会变成猪窝(堆内存满了),你就什么事都干不了了。
JVM的内存被分为了三个主要部分:新生代,老年代和永久代。 新生代:刚创建对象,先存放在新生代;老年代:如果对象频繁被使用,对象放入老年代;永久代指内存的永久保存区域,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域。GC不会在主程序运行期对永久区域进行清理,所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。新生代发生的gc称为Young Gc,这类型的gc对性能影响较小,老年代发生的gc叫full gc,是我们性能调优需要关注的重点,full gc会暂停用户进程,对性能影响较大,如果频繁发生full gc就需要进行调优了,理想状态是很久才发生一次full gc。
以下是使用JvisualVM工具监控的gc情况,可以看到有频繁的full gc
也可以使用jstat查看gc的情况,以下是查看java进程的gc情况,其中o列是年老代使用率
重点关注一下几列:
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
如果每次FGC时间超过1s对性能造成较大的影响,频繁的FGC会导致CPU使用率很高,GC 的直接原因是内存不足,可以从内存泄露的角度去查找原因。
JAVA_OPTS="-Server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"
新生代和老年代大小配置
-XX:NewSize 和 -Xmn(-XX:MaxNewSize):指定JVM启动时分配的新生代内存和新生代最大内存。
-XX:SurvivorRatio:设置新生代中1个Eden区与1个Survivor区的大小比值。如果新生代内存是
10M,SurvivorRatio=8,那么Eden区占8M,2个Survivor区各占1M。
-XX:NewRatio:指定老年代/新生代的堆内存比例。在hotspot虚拟机中,堆内存 = 新生代 + 老年代。如果-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆内存的1/5。在设置了-XX:MaxNewSize的情况下,-XX:NewRatio的值会被忽略,老年代的内存=堆内存 - 新生代内存。老年代的最大内存 = 堆内存 - 新生代 最大内存。
-XX:OldSize:设置JVM启动分配的老年代内存大小,类似于新生代内存的初始大小-XX:NewSize。
比如:堆的最大值为128m,则新生代(eden,s1,s1)共128*1/5=25.6,老年代为128*4/5=102;