jvm相关总结

jvm常用参数

 
-XX:+PrintGCDetails -XX:+PrintGC -XX:+PrintGCTimeStamps -Xloggc:file -XX:+PrintHeapAtGC
-XX:+HeapDumpOnOutOfMemoryError   -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath
-Xmx100m -Xms100m -Xmn50m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=64m
-XX:NewRatio=10 -XX:SurvivorRatio=2
-XX:+DisableExplicitGC
-XX:MaxDirectMemorySize
-Xss
 
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)
EC、EU:Eden区容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年轻代GC次数和GC耗时
FGC、FGCT:Full GC次数和Full GC耗时
GCT:GC总耗时<br><br>
 
jstat -gcutil [pid] 60000
jmap -histo:live [pid]     会(也可用于)强制 fullgc  生成文本文件 jmap -dump:live,format=b,file=heap.bin <pid>产生gc收不走的对象
jmap -histo 12309
jmap -dump:format=b,file=文件名 [pid]   不导致fullgc  jmap -dump:live  会导致
jmap -heap pid
jinfo -flags process_id
jhat -J-Xmx1024M [file]
-XX:+HeapDumpBeforeFullGC
 
总流程:
越跑越慢/内存溢出
  jstat查看fgc频率(fgc!=full gc)
    jmap live 不建议用,导致full gc
    jmap dump
    HeapDumpBeforeFullGC
      jhat 不建议
      visualvm
      mat
几个案例:ArrayBlockingQueue,Druid.JdbcSqlStat,jstack线程显式gc,线程池拒绝又放入无限循环栈溢出
 
经验:
如果full gc过于频繁,经查内存未满即fgc了,则基本是显式gc
full gc过于频繁,每次回收前后空间又降不下去,说明有大对象顽固分子进驻回收不掉,要看对象了
full gc过于频繁,每次空间回收也合理,那么就结合youngc晋级对象、dump和代码审查
每次youngc后,堆总大小理想中不应增加,如果增加太多,要警惕,说明有对象晋级或大对象,最好看对象,而且总有一天会引发fullgc频繁
younggc不频繁,建议缩小内存,节约服务器资源
younggc太频繁,看新生代大小和eden区大小
建议 young:old = 4:6 ; eden:s0:s1 = 8:1:1
 
目标:
YoungGC频率不超过2秒/次;
CMS GC频率不超过1天/次;
每次YoungGC的时间不超过15ms;
FullGC频率尽可能完全杜绝;(jstat中的FGC不准确,有可能是cms gc-每次+2fgc,准确看gc日志)

https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247484458&idx=1&sn=09ab6cd3b4187df5bc6e693df57778d5&chksm=96cd4466a1bacd70262a232cf1ae091b528912630a4cb8686c33259b5ca9289e1afc7f334b03&mpshare=1&scene=1&srcid=0818yNvC8sScLesR7jjUdD2X&key=aabb2ccd6a6552351166d5ae3fae009e9ce42be9ad0443233aeef7716871ffa9e9ba6de8ec069a4426ff522833b46ed9fe262772735d065a62d5de188237e8e4172f8e848c350c13c3d4e5d56be9fe7e&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=5aXt5uXOGcgIC7KGUdIaSeIlAcbxVAg2lZI0X5mZh1cMsn46Qh5h0z4PnhyEs5Di

GC主要有YoungGC,OldGC,FullGC(还有G1中独有的Mixed GC,收集整个young区以及部分Old区,提及的概率相对少很多,本篇文章不打算讲解)

截止Java发展到现在JDK9为止,只单独回收Old区的只有CMS GC

对于ParallelOldGC即默认GC在Old满了以后触发的FullGC是没有问题的,jstat命令查看输出结果FGC的值也会相应的+1,即发生了一次FGC。FGC误解主要来自最常用的ParNew+CMS组合,很多人误解FullGC可能是受到jstat命令结果的影响,因为发生CMS GC时,FGC也会增大(但是会+2,这是因为CMS GC的初始化标记和重新标记都会完全的STW,从而FGC的值会+2)。但是,事实上这并没有发生FullGC。jstat命令结果中的FGC并不表示就一定发生了FullGC,很有可能只是发生了CMS GC而已。事实上,FullGC的触发条件非常苛刻,判断是否发生了FullGC最好的方法是通过GC日志,日志中如果有"full gc"的字样,就表示一定发生了Full GC。所以强烈建议生产环境开启GC日志,它的价值远大于它对性能的影响(不用权衡这个影响有多大,开启就对了)。

G1或者ParNew+CMS组合前提下,如果真的发生FullGC,则是单线程完全STW的回收方式(SerialGC),可以想象性能有多差,如果是es,hbase等需要几十个G的堆,那更是灾难。

  • 对象优先在Eden分配。如果新生代放不下对象的时候,object会直接被放到老年代中。
  • 大对象直接进入老年代。
  • 长期存活的对象将进入老年代。一般情况下接受过15次Minor GC后晋升老年代

猜你喜欢

转载自www.cnblogs.com/silyvin/p/9844445.html