性能调优需要掌握的gc知识

       
 
 
       先写结论:

       fullgc频繁,考虑老年代内存是否太小

       YoungGc频繁,考虑年轻代内存是否太小

       YoungGc时间过长,程序中出现了大对象, 增加 -XX:PretenureSizeThreshold,这个值的意思是超过这个值的时候,对象直接在old区分配内存,默认值是0,意思是不管多大都是先在eden中分配内存

        对于Java而言,每个应用都唯一对应一个JVM实例,而每一个JVM实例唯一对应一个堆。堆主要包括关键字 new的对象实例、 this指针,或者数组都放在堆中,并由应用所有的线程共享。堆由JVM的自动内存管理机制所管理,名为垃圾回收—— GC(garbage collection)

       自动垃圾回收机制,简单来说就是寻找 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 的直接原因是内存不足,可以从内存泄露的角度去查找原因。

 

 

   
     在实际开发中,可以在Tomcat的catalina.sh文件中设置JVM的堆内存大小
     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;



 

posted @ 2019-06-02 14:56  wuxiaomiao  阅读(359)  评论(0编辑  收藏  举报