jvm总结
2021-03-13 21:38:07 36 举报
AI智能生成
jvm知识体系总结、问题分析思路
作者其他创作
大纲/内容
-XX:PreTenureSizeThreshold
大对象直接进入老年代
1. 老年代最大连续空闲内存空间大于年轻代所有对象大小
-XX:HandlePromotionFailure jdk1.6 update24之前要设置true
比较历次minor gc晋升对象的大小
2. 是否允许担保失败
老年代空间分配担保
动态年龄判断
minor gc后,survivor区放不下
内存分配策略
minor gc之前
minor gc之后
预估qps
一次请求中生成的对象大小
接口耗时
几个要素
qps*对象大小=一秒生成的对象锁占用的内存空间
eden区大小 / (qps * 对象大小)
发生minor gc的时刻,往前推接口耗时timeout 这段时间内产生的对象 都是被jvm虚拟机栈引用着的
所以, minor gc发生时 存活对象空间 = timeout * qps * 对象大小
minor gc后多少对象生还?
怎么分析多久进行一次minor gc?
qps
1. 每秒产生多少对象
eden区大小
每次执行创建的对象总占用内存
2. 多久进行一次 minor gc
执行的超时时间是多久
timeout * qps * 对象大小
3. 一般minor gc后存活对象有多少
4. survivor区放得下吗?
5. 有没有因为survivor 区放不下导致频繁full gc
6. 会不会因为动态年龄判断 导致晋升老年代
年轻代优化分析思路
基调:尽量避免对象过快进入老年代
survivor过小,放不下minor gc后的对象
大量对象进入老年代的场景
老年代优化思路
尽量让每次minor gc 后的存活对象小于survivor的50%
尽量让对象不进入老年代,减少full gc频率
总方针/指导思想
假设执行耗时和每次执行创建的对象大小不变
多久发生一次minor gc
minor gc后存活对象变多少
多久一次 full gc
系统负载扩大10倍、百倍后
思路
内存溢出
线程死锁
etc...
dump分析能力
每行gc日志的含义
回收大小的计算
minor gc后,年轻代空间和老年代空间各自的变化, 如何计算多少存活对象进入/晋升到了老年代
gc日志分析能力
能力
笔记
案例分析
bi报表后台,每次查询大sql 一次查询很多数据
后台系统,分页查大量数据
执行耗时较长
对响应的停顿不敏感
年轻代空间比例调大
避免survivor区放不下 导致这些对象快速进入老年代 而发生频发full gc
处理
低频 但每次执行产生的对象比较多
高并发服务
系统的类型
监控jvm运行情况: jstat -gc {pid} 间隔 次数
查看/动态变更进程参数 jinfo
jmap -dump会导致系统停顿注意不要在线上机器直接执行,要先拉出再执行
jvm内存情况 jmap
jstack pid > thread.dump
线程栈 jstack
实用工具
当公司缺乏图形化监控工具的时候,这些最基础的命令 就显得特别重要了 => 必须掌握 而且一定要熟练
eden区的对象增长速率有多快
young gc频率多高
一次young gc耗时多长
young gc后多少对象存活
老年代的对象增长速率多高
full gc频率多高
一次 full gc耗时多少
jvm内存运行模型分析
512M
未主动设置,默认的配置太小
cglib等技术动态生成了太多类
元数据区OOM
java虚拟机栈
堆内存
nio
sun.misc.Unsafe
堆外内存 direct buffer memory
1. 自动dump
2. oom发生位置: 栈、堆、元数据区
mat histogram
3. 分析dump找到 占用内存的一个或一群对象
mat 支配树 dominator tree
4. 谁引用这些对象
定位具体代码位置
5. 哪个线程导致
判断内存划分是否合理
分析gc日志
分析步骤
内存溢出OOM
cpu负载、使用率
内存情况
网络io
磁盘io
线程数
系统压力
各区域内存情况、走势
young gc频率和耗时
full gc频率和耗时
gc情况
jvm
短信次数
请求异常次数
...
业务指标
cpu使用率、负载
内存告警
full gc频率告警
full gc 耗时告警
告警
监控
内存区域
垃圾回收过程
加载
验证
准备
解析
连接
初始化
过程
Ojbect为例
破坏双亲委派会怎么样?
双亲委派
类加载
引用计数
reference count
复制回收
copy
标记-清除
mark-sweep
标记-整理
mark-compact
分代回收
Generational Collection
gc算法
minor gc前分配担保失败
minor gc后 survivor区放不下的那部分对象
n > 1
年龄n及以下的对象总大小大于 survivor区空间的一半,则年龄n及以上的对象进入老年代
如果survivor区的年龄都是1,即使超过 50%也不会触发
minor gc后动态年龄判断
超龄15
长期存活对象
对象什么时候进入老年代
老年代空闲空间放不下晋升对象
minor gc前,如果老年代最大连续空间小于历次晋升对象的大小,则先进行full gc
分配担保
cms 中老年代占用空间大于 -XX:CMSInitiatingOccupancyFaction
脑抽执行 System.gc()
元数据区metaspace 满了
full gc什么时候发生
调整内存分配比例
内存分配不合理,导致对象频繁进入老年代, 进而导致频繁 full gc
dump分析
存在内存溢出的情况,老年代驻留了大量对象,只要有一点点对象晋升到老年代 就发生full gc
永久代/元数据区 类太多了
频繁发生full gc的可能原因
userAuthygc 50msfull gc 400+ms
比年轻代回收慢上10倍以上
存活久
对象大
存活对象多
老年代中对象的特征
标记和清理的工作量大还要整理内存碎片就更慢了
空间敏感
老年代回收频率低
时间敏感
年轻代回收频率高
频率
为什么老年代回收比较慢
最早的回收器,单线程 stw
Serial
可以认为 Serial 的多线程版本,参数都支持
多线程
指定 -XX:UseParNewGC
设置线程数 -XX:ParallelGCThreads
参数
ParNew
单位时间内回收更多垃圾
关注回收吞吐量/回收率
控制停顿时间 -XX:MaxGCPauseMillis
系统运行时间 /(系统运行时间 + GC停顿时间)
默认为 99
设置吞吐量大小 -XX:GCTimeRatio
可自适应调节策略
不能和cms配合使用,老年代选用cms后,年轻代只能用 ParNew
Parallel Scavenge
年轻代回收器
一般的组合 ParNew + CMS
最短回收停顿时间为目的的收集器
内存碎片
标记-清除 算法本身的问题
指定cms: -XX:UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
多少次fullgc后进行整理: -XX:CMSFullGCsBeforeCompaction=0
回收后进行碎片整理
触发cms回收的比例: -XX:CMSInitiatingOccupancyFraction=55
只是用设置的比例,不让jvm自动调整 -XX:+UseCMSInitiatingOccupancyOnly
避免浮动垃圾
stw,但是只标记gc roots直接引用的 非常快
初始标记
老年代存活对象比较多,追踪大量对象,耗时比较长
并发标记
stw,这边有可能由于待回收的垃圾对象引用太多,停顿会比较久
重新标记
并发清理
四个阶段
标记-清除算法的缺陷
-XX:+UseCMSCompactAtFullCollection 默认开启,表示fullgc之后 进行内存碎片整理
-XX:CMSFullGCsBeforeCompaction=0 执行多少次fullgc之后 进行一次内存碎片整理默认为0,表示fullgc之后都会整理
如何处理,打开2个参数
1. 内存碎片
gc线程数 = (cpu核数 + 3)/4
并发清理阶段 回收线程和 系统线程同时工作
2. 消耗cpu资源
cms在并发清理阶段,系统还在运行,此时产生的垃圾在本次是处理不了的,称为“浮动垃圾”
如果并发清理时候,老年代空间放不下此时产生的“浮动垃圾”会发生 Concurrent Mode Failure
退化成 Serial Old 再次进行垃圾收集
默认92%
一般设置成55% 、65%
所以cms收集器要预留一部分空间 -XX:CMSInitiatingOccupancyFaction 触发cms的比例
3. “浮动垃圾”
三个问题
CMS(Concurrent Mark Sweep)
单线程
停顿收集
cms的后备预案
Serial Old
Parallel Old
老年代回收器
-XX:MaxGCPauseMills
可以设置垃圾回收的预期停顿时间
最大2048个
年轻代占多少个 region,是g1根据预设停顿时间来动态评估的
年轻代初始占比 -XX:G1NewSizePercent=5
年轻代最大占比 -XX:G1MaxNewSizePercent=60
将java堆内存拆分为多个大小相等的region
追踪每个region可以回收的对象大小和预估时间
垃圾回收价值
老年代内存占整个堆内存 -XX:InitiatingHeapOccupancyPercent=45 时候发生
最终标记
stw
复制算法
默认8次 -XX:G1MixedGCCountTarget=8
可以进行多次
回收失败后进行 serial old full gc
混合回收
大内存堆的进程
停顿时间敏感
适用场景
G1(Garbage First)
垃圾回收器
0 条评论
回复 删除
下一页