promotion failed成因和解决方法

1.什么是promotion failed

promotion是“晋升”的意思,promotion failed当然是“晋升失败”了,在JVM GC的世界里,也有类似人类社会中的分等分级的概念,我所说的是对象是被区分对待的,有用(存在引用)的对象会在垃圾回收的过程中被晋升到较高等级的内存区域,然而有时候会出现一些意外,导致对象晋升失败,这就是promotion failed。

2.什么情况下会发生promotion failed

如果说整个堆一共分为新生代(level=0)和老年代(level=1)两个等级的话,那么年轻代也分为eden(伊甸园)区和survivor(幸存)区两个内存等级。注意对象晋升的大环境是年轻代GC,因为老年代已经是最高等级区域了,不存在再次晋升的情况。对象晋升的路线是eden→survivor或者是eden→old,因为当有用对象从eden区域晋升到survivor区域的时候有可能会晋升失败,因此会GC线程会再尝试直接往老年代晋升,同样晋升有可能失败。

2.1.那么什么时候会被认为是晋升失败呢?

有两种情况:

  1. 一种情况是基于历史统计数据,比如统计数据显示历史上平均每次晋升对象的大小是av_promo,而当前老年代的空间并不足以存放av_promo大小的对象,则GC线程认为实际晋升的过程中可能会发生失败,晚失败不如早点失败,这种策略虽然会略有些悲观,但是实际上是这么做的,于是GC线程告诉堆发生了一次GC失败事件便终止了这次回收动作。
  2. 另一种情况是历史统计数据显示这次老年代有足够的空间来支持对象晋升,但是实际执行的过程中出了点小意外,有对象晋升失败了,那么GC线程同样会告诉堆发生了一次垃圾回收失败事件。

3.发生promotion failed会有什么后果

显然GC线程在回收年轻代的时候发生promotion failed都会乖乖地告诉堆,问题是堆知道这个事情之后会很麻烦,比如背后存在一个默默关心这个事件的CMS线程同学。CMS线程每隔一段时间会去检查一些条件来确定是不是要来一次CMS GC,其中一个条件便是有没有发生过promotion failed,CMS GC被触发了。说起CMS GC,很多FGC的统计会把CMS GC算作一次FGC,包括CMS自己也认为自己是FGC,这里有一种解释:CMS GC需要被关注!!!因为CMS触发的结果是STW(CMS的初始标记和重新标记阶段),这对应用来说影响很大,因为STW意味着所有Java线程都会被block,JVM会在安全点将所有Java线程挂起,安全点的存在是为了让一些不安全的事情顺利的发生,比如CMS GC中的对象标记操作 。

4.如果尽量避免发生promotion failed

从发生promotion failed的条件可以看出,promotion failed主要是因为对象被晋升的目标区域没有足够的空间存放被晋升对象,两个方法入手可以减少promotion failed

  • 1.减少promotion动作,调大年轻代和survival区
  • 2.老年代腾出足够空间,减少老年代碎片,腾出连续的内存空间存放大对象,如果使用CMS垃圾回收器可以使用XX:CMSInitiatingOccupancyFractionUseCMSCompactAtFullCollection参数
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左林右李02

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值