一次线上故障之Java对象的一生简单总结
“对象”的一生
像往常一样,早上10点到了公司,赵小八打开电脑收到了PM前一天晚上发来的推荐系统新需求,内心一万只草泥马飘过,思索了半天,打开IDEA开始了“愉快的”new对象之旅。
垃圾回收器老哥:你这样疯狂的嚯嚯对象,有考虑过我的感受吗?
赵小八:你谁啊?我new对象干你啥事?
垃圾回收器老哥:年轻人火气别这么大,既然你这么说那请耗子尾汁。
赵小八:呵,你哥我是被吓大的
垃圾回收器老哥:年轻人不讲武德...
没两天,小八翘着尾巴给PM说,功能上线了,刚没一会儿PM骂骂咧咧的找来了,这tm为啥有时候能出来内容有时候出不来啊,小八菊花一紧赶紧查起了问题,先搂监控接口平均耗时从200ms涨到了300ms,小八心想,我不过就多new了几个对象,怎么tm的影响会这么大,同时DBA同学反馈资源监控正常,看来只能搂业务日志看看了,可是业务日志也并没有什么问题,难道GC有问题?果不其然,GC日志像疯了一样的刷日志。小八赶紧让运维紧急回滚线上代码并dump了一份GC日志分析了起来。
现场代码复原
上面这段代码是一个简化版的用户推荐系统,真实情况下加载需要加载的物料除机器学习物料、商业物料外,还有其他各种例如:运营物料、曝光物料、关系物料等等。
当一个真实用户请求过来之后,上面提到的这些物料就需要全部被加载进来。对象首先从新生代中被创建出来,接着经过一段时间GC后,最后存活下来的对象成功晋级到老年代,那么对象是在什么情况下成功晋级到老年代的呢?
case1:对象经历15次GC
小八疯狂的new对象,此时新创建的都被分配到Eden区,如下图:
小八继续疯狂new对象,直到jvm老哥的Eden区放不下更多的对象了,于是触发了一次youngGC,通过这次youngGC之后,只有Context1对象被回收,剩余存活对象进入到了Survivor1里面,如下图:
第一次youngGC结束后,小八又开始了new对象的神操作
没一会儿,jvm又开始了youngGC,此时Eden区和Survivor1里面的存活对象全部移入到Survivor2中,剩余垃圾对象被回收。
就这样反反复复经历了15次youngGC的折腾,还没有被垃圾回收掉的对象最终进入了Old区
case2:动态年龄判断
小八疯狂的new对象
小八继续疯狂new对象,直到jvm老哥的Enden区放不下更对的对象了,于是触发了一次youngGC
经过此次youngGC后,剩余存活对象内存占用大小超过了survivor1区大小的50%,比如:survivor1区大小为50M,而进入到survivor1区的存活对象大小为30M,此时会将当前存活时间最久的对象直接晋升到老年代(存活时间:经历过GC次数最多的对象),此时Context2对象和Context3对象进入到老年代
case3:空间担保机制
小八上线的用户推荐系统,JVM内存的划分情况为:整个堆大小为5G,其中老年代2.5G,新生代2.5G,其中新生代中Eden区:Survivor区=8:2,即Eden区大小为2G,两个Survivor区大小各为250M。
在晚高峰的时候一下子涌入1000人查看推荐列表,一个用户消耗的JVM内存达到了500kb,那么在一秒内就消耗了500M,那么就意味着4秒钟就会产生一次youngGC,假设每次GC后剩余的存活对象为300M,由于300M大小的存活对象无法在survivor区中存放下,此时就触发了空间担保机制。
小八疯狂的new对象
直到发生第一次youngGC,但是一次youngGC后剩余的存活的对象大小Survivor区无法容纳下,此时所有存活对象会直接进入到Old区
在新生代没有足够的内存存储新产生的对象时,老年代会判断自己的区域剩余的内存空间是否能够放得下历代youngGC后剩余存活对象(假设历代youngGC剩余存活对象大小为300M),假设此时老年代还有1G大小的可用内存,那么此次youngGC后剩余的存活对象将直接进入到老年代;假设此时老年代剩余可用内存大小为200M,那么就会触发一次OldGC,OldGC完成后产生的空闲空间大于300M,此时会将新生代的存活对象放入老年代,如果OldGC后剩余的空闲空间小于300M,那么不好意思,就会抛出OOM了。
一图总结Java对象流转情况
上图便是整个Java对象一生经历的流程,流程图相对比较复杂一点,从上往下对照前面讲到的三种情况,相信还是比较容易理解的。
当然图中没有画图新生代触发OOM的情况,可以试想一下Eden区在什么时候会触发OOM?答案在下篇文章给出。
总结
通过一个实际线上案例,讲述了Java对象在不同情况下在JVM中经历的一生。通过本文大家可以尝试将该流程套用到自己公司的项目里面,来分析自己负责的项目是否有类似的问题,或者通过本篇文章来尝试优化自己的项目。另外本文的内容可能会有某些地方讲解的不合适,欢迎有问题的朋友和我私聊探讨。
在上篇文章中留了一个问卷调查,结论如下:总投票人数7人,其中最想了解的技术是SpringCloud,最喜欢的分享方式是图文结合。虽然投票人数比较少,但我相信投票的真实性,后续我会以这个结论为导向,分享更多实用的内容给大家。
打个小广告,年后大家有换个工作氛围的朋友或者身边有想法的朋友,快手研发、运维、产品、运营全部岗位都有你想要的坑位,各种新业务发展速度快,机会多多,面试流程反馈速度超快,欢迎朋友们自荐或者推荐朋友来一起做点有意义的事。
特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢
一次线上故障之Java对象的一生简单总结相关推荐
- 从一次线上故障思考Java问题定位思路,java初级面试笔试题
我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...
- 从一次线上故障思考Java问题定位思路
问题出现:现网CPU飙高,Full GC告警 CGI 服务发布到现网后,现网机器出现了Full GC告警,同时CPU飙高99%.在优先恢复现网服务正常后,开始着手定位Full GC的问题.在现场只能够 ...
- JAVA 线上故障排查套路,从 CPU、磁盘、内存、网络到GC 一条龙!
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数 ...
- JAVA 线上故障排查完整套路,从 CPU、磁盘、内存、网络、GC 一条龙!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:fredal https://fredal.xin/java ...
- JAVA 线上故障排查完整套路!牛掰!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源丨8rr.co/kV3R 线上故障主要会包括 CPU.磁盘.内 ...
- JAVA 线上故障排查指南!
来源:https://fredal.xin/java-error-check 线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依 ...
- 从 CPU、磁盘、内存、网络、GC 一条龙!JAVA 线上故障排查完整套路
线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍.同时例如jstack.jmap等工具也是不囿于一个方面的问题的,基 ...
- java gc日志乱码_6000+字,30+张图。JAVA线上故障排查全套路总结。
fredalxin|https://sourl.cn/duWZhd 线上故障主要会包括 cpu.磁盘.内存以及 网络 问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次 ...
- 一整套Java线上故障排查技巧,爱了!
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:腾讯推出高性能 RPC 开发框架 个人原创100W+访问量博客:点击前往,查看更多 来源:fredal.xin/ ...
最新文章
- 深度学习和机器学习_面试问题(二)
- linux查看apache端口,linux系统下Apache服务启动时80端口报错
- A beginner’s guide to Cache synchronization strategies--转载
- 售票pv操作java实现_随时随地打印手机照片,佳能瞬彩PV-123体验评测
- Redis 安装配置(一)
- sp许可证查询 旧sp电信经营许可证查询 电信业务
- JAVA基础面试题——继承
- IAST技术进阶系列(四):DevOps流水线敏捷实践
- 函数计算机math,Math数学函数
- 用c语言编写一个日期计算器
- Android各厂商自启动管理界面
- Forcing close of thread
- 论文的系统 排版软件Latex
- Ubuntu 修改用户名
- JAVA后端生成树算法,从指定的叶子节点到树根生成树,从树根到所有叶子结点
- [第0章]欢迎使用CSDN-markdown编辑器(新)
- 2020 Vue 基于Element-UI开发 手动导入并使用Timeline组件(附组件文件)查看快递信息
- 在Debian环境下架设PPPoE效劳器-2
- 未来十年互联网十大发展趋势
- 介绍深度卷积神经网络中各种类型的模型