JVM调优实战:GC、Parallel、CMS、G1 常用参数,G1介绍、CPU100%排查

OOM:OutOfMemory。内存溢出

cpu 100%: 使用top,查看占用cpu比较高的进程,使用top -Hp  进程ID ,查看对应的占用cpu较高的线程。如果是java应用,使用 jstack 导出该线程的堆栈。然后查看哪个方法(栈帧)消耗时间  jstack。

内存飙高: 导出堆内存 jmap,使用jhat 、jvisualvm、mat 等等 进行分析。

如何监控JVM: jstat、jvisualvm 等等

jstack dump

jstack 969 > test.txt    :  jstack  线程ID >  文件名

8. jinfo pid 

9. jstat -gc 动态观察gc情况 / 阅读GC日志发现频繁GC / arthas观察 / jconsole/jvisualVM/ Jprofiler(最好用)
   jstat -gc 进程ID 500 : 每个500个毫秒打印GC的情况
   
   1:已经上线的系统不用图形界面用什么?(cmdline arthas)
   2:图形界面到底用在什么地方?测试!测试的时候进行监控!(压测观察)

10. jmap - histo 进程ID ,查找有多少对象产生
   jmap - histo 进程ID | head -20  列出前20个

11. jmap -dump:format=b,file=xxx pid :

    线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)
    1:设定了参数HeapDump,OOM的时候会自动产生堆转储文件
    2:<font color='red'>很多服务器备份(高可用),停掉这台服务器对其他服务器不影响</font>
    3:在线定位(一般小点儿公司用不到)
* 为什么需要在线排查?
   在生产上我们经常会碰到一些不好排查的问题,例如线程安全问题,用最简单的threaddump或者heapdump不好查到问题原因。为了排查这些问题,有时我们会临时加一些日志,比如在一些关键的函数里打印出入参,然后重新打包发布,如果打了日志还是没找到问题,继续加日志,重新打包发布。对于上线流程复杂而且审核比较严的公司,从改代码到上线需要层层的流转,会大大影响问题排查的进度。 
* jvm观察jvm信息
* thread定位线程问题
* dashboard 观察系统情况
* heapdump + jhat分析
OOM产生的原因多种多样,有些程序未必产生OOM,不断FGC(CPU飙高,但内存回收特别少)

G1

Cset = collectionSet   一组可被回收的分区的集合。

扫描二维码关注公众号,回复: 11373484 查看本文章

在CSet中存活的数据会在GC过程中被移动到另一个可用分区,CSet中的分区可用来自Eden空间、survivor空间或者老年代。CSet会占用不到整个堆空间的1%大小。

Rset = RememberedSet 每一个region 中都有一组set,记录着其它region中的对象到本region的引用。

Rset的价值在于,垃圾回收器不需要扫描整个堆查找谁引用了当前分区中的对象,只需要扫描RSet即可。

新老年代比例  5%-60% 动态。一般不用手工指定,因为这是G1预测停顿时间的基准。

humongous object :超过单个region的50%

GC何时触发

YGC:  Eden空间不足,多线程并行执行。

FGC:old空间不足,System.gc()

16. G1是否分代?G1垃圾回收器会产生FGC吗?  是,会。G1 java 10以前是串行FULLGC,之后是并行FullGC

17. 如果G1产生FGC,你应该做什么?

      1. 扩内存
      2. 提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)
      3. 降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)

G1 中的MixedGC  = CMS,初始标记、并发标记、重新标记、并行筛选回收

XX:InitiatingHeapOccupacyPercent  默认值45%。 当YGC超过这个值,启动MixedGC。在这之前是serial

三色标记

G1使用的是 SATB ,cms 使用的是incremental update。

 ### GC常用参数

* -Xmn -Xms -Xmx -Xss
  年轻代 最小堆 最大堆 栈空间
* -XX:+UseTLAB
  使用TLAB,默认打开
* -XX:+PrintTLAB
  打印TLAB的使用情况
* -XX:TLABSize
  设置TLAB大小
* -XX:+DisableExplictGC
  System.gc()不管用 ,FGC
* -XX:+PrintGC
* -XX:+PrintGCDetails
* -XX:+PrintHeapAtGC
* -XX:+PrintGCTimeStamps
* -XX:+PrintGCApplicationConcurrentTime (低)
  打印应用程序时间
* -XX:+PrintGCApplicationStoppedTime (低)
  打印暂停时长
* -XX:+PrintReferenceGC (重要性低)
  记录回收了多少种不同引用类型的引用
* -verbose:class
  类加载详细过程
* -XX:+PrintVMOptions
* -XX:+PrintFlagsFinal  -XX:+PrintFlagsInitial
  必须会用
* -Xloggc:opt/log/gc.log
* -XX:MaxTenuringThreshold
  升代年龄,最大值15
* 锁自旋次数 -XX:PreBlockSpin 热点代码检测参数-XX:CompileThreshold 逃逸分析 标量替换 ... 
  这些不建议设置

### Parallel常用参数

* -XX:SurvivorRatio
* -XX:PreTenureSizeThreshold
  大对象到底多大
* -XX:MaxTenuringThreshold
* -XX:+ParallelGCThreads
  并行收集器的线程数,同样适用于CMS,一般设为和CPU核数相同
* -XX:+UseAdaptiveSizePolicy
  自动选择各区大小比例

### CMS常用参数

* -XX:+UseConcMarkSweepGC
* -XX:ParallelCMSThreads
  CMS线程数量
* -XX:CMSInitiatingOccupancyFraction
  使用多少比例的老年代后开始CMS收集,默认是68%(近似值),如果频繁发生SerialOld卡顿,应该调小,(频繁CMS回收)
* -XX:+UseCMSCompactAtFullCollection
  在FGC时进行压缩
* -XX:CMSFullGCsBeforeCompaction
  多少次FGC之后进行压缩
* -XX:+CMSClassUnloadingEnabled
* -XX:CMSInitiatingPermOccupancyFraction
  达到什么比例时进行Perm回收
* GCTimeRatio
  设置GC时间占用程序运行时间的百分比
* -XX:MaxGCPauseMillis
  停顿时间,是一个建议时间,GC会尝试用各种手段达到这个时间,比如减小年轻代

### G1常用参数

* -XX:+UseG1GC
* -XX:MaxGCPauseMillis
  建议值,G1会尝试调整Young区的块数来达到这个值
* -XX:GCPauseIntervalMillis
  ?GC的间隔时间
* -XX:+G1HeapRegionSize
  分区大小,建议逐渐增大该值,1 2 4 8 16 32。
  随着size增加,垃圾的存活时间更长,GC间隔更长,但每次GC的时间也会更长
  ZGC做了改进(动态区块大小)
* G1NewSizePercent
  新生代最小比例,默认为5%
* G1MaxNewSizePercent
  新生代最大比例,默认为60%
* GCTimeRatio
  GC时间建议比例,G1会根据这个值调整堆空间
* ConcGCThreads
  线程数量
* InitiatingHeapOccupancyPercent
  启动G1的堆空间占用比例

CPU100%排查

1.执行 top 命令,查看占用cpu使用率最高的 pid 进程

2.使用 top -Hp  pid ,键入大写P,按照cpu使用率排序,找出最耗cpu的线程id

3.将线程 id 转换成 16 进制(堆栈里面线程id 是16进制表示的)

4.使用 jstack pid | grep '线程id(16进制)'  -C5 --color  查看最耗cpu的线程

5.找到对应代码进行排查。

参考 https://www.cnblogs.com/heluan/p/9601060.html

猜你喜欢

转载自blog.csdn.net/dandanforgetlove/article/details/106123999
今日推荐