点击蓝色“程序猿DD”关注我哟

加个“星标”,不忘签到哦

转载自公众号:字节观


关注我,回复口令获取可获取独家整理的学习资料:

001 :领取《Spring Boot基础教程》

002 :领取《Spring Cloud基础教程》

最近新上线的系统偶尔会报FullGC时间过长(>1s)的告警,查看GC日志,如下图所示:

看到GC日志,我第一时间关注到的不是GC耗时,而是GC触发的原因:Metadata GC Threshold。也就是FullGC触发的原因是因为Metaspace大小达到了GC阈值。在监控系统里面看了一下Metaspace的大小变化趋势,如下图所示:

按照以往的经验,Metaspace在系统稳定运行一段时间后占用空间应该比较稳定才对,但是从上图来看,Metaspace显然是呈现大幅波动。为什么呢?

相关知识

我们知道Metaspace主要存储类的元数据,比如我们加载了一个类,那么这个类的信息就会按照一定的数据结构存储在Metaspace中。Metaspace的大小和加载类的数目有很大关系,加载的类越多,Metaspace占用内存也就越大。

Metaspace被分配于堆外空间,默认最大空间只受限于系统物理内存。跟它相关的比较重要的两个JVM参数:

-XX:MetaspaceSize -XX:MaxMetaspaceSize。

MaxMetaspaceSize大家从名字也能猜到是指Metaspace最大值,而MetaspaceSize可能就比较容易让人误解为是Metaspace的最小值,其实它是指Metaspace扩容时触发FullGC的初始化阈值,在GC后该值会被动态调整:如果本次GC释放了大量空间,那么就适当降低该值,如果释放的空间较小则适当提高该值,当然它的值不会大于MaxMetaspaceSize.

另外一个相关知识是:Metaspace中的类需要满足什么条件才能够被当成垃圾被卸载回收?条件还是比较严苛的,需同时满足如下三个条件的类才会被卸载:

1、该类所有的实例都已经被回收;

2、加载该类的ClassLoader已经被回收;

3、该类对应的java.lang.Class对象没有任何地方被引用。

排查过程

我们可以回过头再细看GC日志,可以看出Metaspace已使用内存在FullGC后明显变小(372620K -> 158348K),说明Metaspace经过FGC后卸载了很多类。从这点来看,我们有理由怀疑系统可能在频繁地生成大量”一次性“的类,导致Metaspace所占用空间不断增长,增长到GC阈值后触发FGC。

那么这些被回收的类是什么呢?为了弄清楚这点,我增加了如下两个JVM启动参数来观察类的加载、卸载信息:

-XX:TraceClassLoading -XX:TraceClassUnloading

加了这两个参数后,系统跑了一段时间,从Tomcat的catalina.out日志中发现大量如下的日志:

到此基本可以确定Metaspace增长的元凶是这些类,那么这些类sun.reflect.GeneratedSerializationConstructorAccessorXXX是干嘛的呢?又是从哪里引进来的呢?我也是一脸懵逼~~

根据类名Google了一把,找到了@寒泉子写的《从一起GC血案谈到反射原理》,这篇文章对这些类的来源解释得很透彻。在这里我简单总结如下:

Method method = XXX.class.getDeclaredMethod(xx,xx);
method.invoke(target,params);

这些类的来源是来自反射,类似上面所示的反射代码应该大家都写过或者看过,我们常用的大多数框架比如Spring、Dubbo等都大量使用反射。出于性能的考虑,JVM会在反射代码执行一定次数后,通过动态生成一些类来将”反射调用”变为“非反射调用”,以达到性能更好。而这些动态生成的类的实例是通过软引用SoftReference来引用的。

我们知道,一个对象只有软引用SoftReference,如果内存空间不足,就会回收这些对象的内存;如果内存空间足够,垃圾回收器不会回收它。只要垃圾回收器没有回收它,该对象就可以被使用。那么究竟在什么时候会被回收呢?

SoftReference中有一个全局变量clock代表最后一次GC的时间点,有一个属性timestamp,每次访问SoftReference时,会将timestamp其设置为clock值。

当GC发生时,以下几个因素影响SoftReference引用的对象是否被回收:

1、SoftReference对象实例多久未访问,通过clock - timestamp得出对象大概有多久未访问;

2、内存空闲空间的大小;

3、SoftRefLRUPolicyMSPerMB常量值;

是否保留SoftReference引用对象的判断参考表达式,true为不回收,false为回收:

clock - timestamp <= freespace * SoftRefLRUPolicyMSPerMB 

说明:

clock - timestamp:最后一次GC时间和SoftReference对象实例timestamp的属性的差。就是这个SoftReference引用对象大概有多久未访问过了。

freespace:JVMHeap中空闲空间大小,单位为MB。

SoftRefLRUPolicyMSPerMB:每1M空闲空间可保持的SoftReference对象生存的时长(单位ms)。这个参数就是一个常量,默认值1000,可以通过参数:-XX:SoftRefLRUPolicyMSPerMB进行设置。

查看了一下我们系统的JVM参数配置,发现我们把SoftRefLRUPolicyMSPerMB设置为0了,这样就导致软引用对象很快就被回收了。进而导致需要频繁重新生成这些动态类。

为了验证这个猜测,我把SoftRefLRUPolicyMSPerMB改成了6000进行观察,发现果然猜得没错。系统启动后不久Metaspace的使用空间基本保持不变了,运行几天后也没再出现因为Metaspace大小达到阈值而触发FGC。至此问题解决。

References

[1] 假笨说-从一起GC血案谈到反射原理: https://mp.weixin.qq.com/s/5H6UHcP6kvR2X5hTj_SBjA?

[2] Java的强引用,软引用,弱引用,虚引用及其使用场景: http://blogxin.cn/2017/09/16/java-reference/


推荐阅读

  • MySQL跑在CentOS 6 和 7上的性能比较

  • Spring Boot 配置文件中的花样,看这一篇足矣!

  • Mybatis的工作原理,你了解过吗?

  • 理解 IntelliJ IDEA 的项目配置和Web部署

  • 如何告别那些没卵用的线上告警!

活动介绍:自律到极致-人生才精致:第8期

活动奖励:《小灰的算法之旅》* 10

扫描下面二维码签到参与

关注我,加个星标,不忘签到哦~

2019

与大家聊聊技术人的斜杠生活

Metaspace 引起的 FullGC 问题排查过程及解决方案相关推荐

  1. 一次堆外OOM问题的排查过程

    转载自   一次堆外OOM问题的排查过程 背景 线上服务有一台机器访问不通(一个管理平台),在公司的服务治理平台上查看服务的状况是正常的,说明进程还在.进程并没有完全crash掉.去线上查看机器日志, ...

  2. 内存很空却频繁gc_记一次不太成功的频繁 full gc 排查过程

    上周自己负责的一个应用出现频繁full gc的问题,不得不尝试优化一下.第一次做这种事只能先看看网上的文章,然后亲自尝试怎么去完成减少full gc的频率,降低young gc的频率这一目标.虽然最终 ...

  3. 一次线上服务fullGC原因排查

    2017年12月09日 21:39:46 阅读数:384 一.现象 早上九点多又收到了fullGC次数过高的应用监控告警{P1}{故障}JVM Old GC all(#3) full_gc_count ...

  4. java gc full gc_记一次Java服务频繁Full GC的排查过程

    现象 从监控来看,堆内存是够用的,但是频繁触发Full GC,每秒钟三次,每次耗时三四秒. image.png 结合Young GC的信息和堆内存的使用情况,可以发现新生代的内存够用,老生代的内存不够 ...

  5. java cms cpu占用率_cpu使用率过高和jvm old占用过高排查过程

    今天断断续续的收到管理平台的异常报警,cpu占用过高和jvm old占用过高,这个时候赶紧去排查原因,下面记录了我的排查过程,可能里面还有不正确的地方,欢迎各位大佬指正,也欢迎大家关于类似的案例一起交 ...

  6. 实战派:一次kafka卡顿事故排查过程!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 等你归去来 来源 | www.cnblogs. ...

  7. 干货!一次kafka卡顿事故排查过程

    由于一次功能上线后,导致某数据量急剧下滑,给我们紧张的呢!排查过程也是个学习过程!抛开结果,方法论可供参考- 1. 确认问题的真实性? 被数据部门告知,某数据量下滑严重,当时即知道问题的严重性.且该问 ...

  8. 多队列 部分队列没有包_记一次TCP全队列溢出问题排查过程

    简介:记一次TCP全队列溢出问题排查过程 1. 前言 本文排查的问题是经典的TCP队列溢出问题,因TCP队列问题在操作系统层面没有明显的指标异常,容易被忽略,故把排查过程分享给大家. 2. 问题描述 ...

  9. 一次堆外内存泄露的排查过程

    转载自  一次堆外内存泄露的排查过程 最近在做一个基于 websocket 的长连中间件,服务端使用实现了 socket.io 协议(基于websocket协议,提供长轮询降级能力) 的 netty- ...

最新文章

  1. oracle hot patch david,Oracle EBS使用adpatch工具打patch过程(hotpatch mode)
  2. 6月第1周回顾:华为再现猝死 中国成全球最大宽带市场
  3. 皮一皮:可怜的西瓜...
  4. python【蓝桥杯vip练习题库】BASIC-18 矩形面积交(线段交)
  5. 在VS.NET2003中无法新建C#项
  6. 程序员面试题精选100题(02)-设计包含min函数的栈[数据结构]
  7. 【Android开发】线程与消息处理-Handler消息传递机制之Looper
  8. 吴恩达机器学习 逻辑回归 作业2(芯片预测) Python实现 代码详细解释
  9. 若依框架如何进行单元测试
  10. 考研复习计划怎么做?MindManager来帮你!
  11. 30页不容错过的超赞项目管理PPT
  12. HDU - 4567 Brilliant Programmers Show 2013长沙邀请赛
  13. 学习信号量 sem_init、sem_destroy、sem_post、sem_wait、sem_trywait、sem_getvalue
  14. 卜算子.咏梅 英文版
  15. 用VS2005打开方案出现“此安装不支持该项目类型
  16. 快速搭建仓储管理系统
  17. 地方征信平台第2讲:河北省征信
  18. PIC 1508 TIM1的定时器中断使用
  19. linux p4使用心得
  20. 基于python和opencv的图像分割旋转裁剪

热门文章

  1. linux ubuntu kubuntu与xubuntu等各版本差别
  2. linux shell 脚本嵌套调用 获取脚本自身文件名
  3. linux c 查看 结构体 宏 函数 关键字定义
  4. zend studio自动添加文件注释和方法注释
  5. 代码注入之远程线程篇
  6. Linux C编程--进程间通信(IPC)5--System V IPC 机制1--消息队列
  7. Android中实现双缓冲(画板应用)和XML文件定义菜单
  8. java设计模式---合成模式
  9. Linux密码文件passwd和shadow分析
  10. Android--判断发送短信后的状态/发送成功Or发送失败