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