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