本文来自: PerfMa技术社区

PerfMa(笨马网络)官网

概述

今天要说的这个问题,是我经常面试问的一个问题,只是和我之前排查过的场景有些区别,属于另外一种情况。也许我这里讲了这个之后,会成为不少公司JVM必问之题,所以本文还是值得大家好好看看的,相信也会让你很有收获,我把这个问题简单归纳为Hotspot GC研发工程师也许漏掉了一块逻辑。

如下图所示,在上一次YGC之后,from space的使用率是12%,但是在下一次YGC准备发生的时候,发现from space的使用率变成了99%。

OK,看到这里,请停下来思考10秒钟,想想这个现象是否正常。

  • 如果你觉得这个现象不正常,说明你对JVM内存分析有一定的理解,但还是没有完全理解。
  • 如果你觉得这个现象没问题,绝大部分说明你对JVM内存分配还不够熟悉,极少部分情况说明你对它已经非常熟悉了,对它实现上的优缺点都了如指掌了。

那请问你是属于哪种呢?

其实简化下来的问题就是:

非GC过程中,新创建的对象可能在from space里分配吗?

JVM内存分配

JVM内存分配说简单也简单,说复杂也复杂,不过我这里不打算说很细,因为要扯开讲,基本可以讲几个小时,我这里只挑大家熟知的来聊。暂时把大家归结为上面的第一种情况。

大家知道Java Heap主要由新生代和老生代组成,而新生代又分别由eden+s0(from space)+s1(to space)构成,通常情况下s0或者s1有一块是空的,主要用来做GC copy。

当我们创建一个对象的时候,会申请分配一块内存,这块内存主要在新生代里分配,并且是在eden里分配,当然某些特殊情况可以直接到老生代去分配,按照这种规则,正常情况下怎么也轮不到到from space去分配内存,因此在上次GC完之后到下次GC之前不可能去from space分配内存。

事实是怎样呢

那到底是不是这样呢?从上面的GC日志来看显然不是这样,我之前有过一次经验是这种情况和GC Locker有关,当时在群里要美团的同学把后面的日志发全一点验证下,结果比较意外,不是我之前碰到的情况,因此我要了整个完整的GC日志,下面简单描述下我对这个问题的思考过程。

我拿到GC日志后,第一件事就是找到对应的GC日志上下文,这种诡异的现象到底是偶尔发生的还是一直存在,于是我整个日志搜索from space 409600K, 99%,找到第一次情况发生的位置,发现并不是一开始就有这种情况的,而是到某个时候才开始有,并且全部集中在中间某一段时间里,那我立马看了下第一次发生的时候的上下文,发现之前有过一次Full GC和一次CMS GC

再找了最后一次发生的时候后面的情况

发现也有次Full GC,那综合这两种情况,我基本得出了一个大致的结论,可能和Full GC有关。

源码验证

带着疑惑我开始找相关源码来验证,因为我知道有从from space分配的情况,于是直接找到了对应的方法

从上面的代码我们可以做一些分析,首先从日志上我们排除了GC Locker的问题,如果是GC Locker,那在JDK8下默认会打印出相关的cause,但是实际上gc发生的原因是因为分配失败所致,于是重点落在了should_allocate_from_space

bool should_allocate_from_space() const {
return _should_allocate_from_space;
}

那接下来就是找什么地方会设置这个属性为true,找到了以下源码

这是gc发生之后的一些处理逻辑,并且是full为true的情况,那意味着肯定是Full GC发生之后才有可能设置这个属性set_should_allocate_from_space(),并且也只有在Full GC之后才可能清理这个属性clear_should_allocate_from_space(),那基本就和我们的现象吻合了。

那是不是所有的Full GC发生之后都会这样呢,从上面的代码来看显然不是,只有当!collection_attempt_is_safe() && !_eden_space->is_empty()为true的时候才会有这种情况,这里我简单说下可能的场景,当我们因为分配内存不得已发生了一次Full GC的时候,发现GC效果不怎么样,甚至eden里还有对象,老生代也基本是满的,老生代里的内存也不足以容纳eden里的对象,此时就会发生上面的情况。

不过随着时间的推移,有可能接下来有好转,比如做一次CMS GC或许就能把老生代的一些内存释放掉,那其实整个内存就又恢复了正常,但是这带来的一个问题就是发现后面经常会发生从from space里分配内存的情况,也就是我们这次碰到的问题,直到下次Full GC发生之后才会解封,所以我们哪怕执行一次jmap -histo:live也足以解封。

GC研发工程师漏掉的逻辑?

那这样其实带来了一个新的问题,那就是会让更多的对象尽快晋升到老生代,这会促使老生代GC变得相对比较频繁,我感觉这其实应该算是JVM的一个bug,或许更应该说是GC研发工程师不小心漏掉了一块逻辑。

我觉得一个合理的做法是如果后面有CMS GC,那在CMS GC之后,应该主动clear_should_allocate_from_space(),也就是在CMS GC的sweep阶段执行完之后执行上面的逻辑,这样就会有一定保证,事实上,我们从sweep的源码里也看到了部分端倪,最后调用了gch->clear_incremental_collection_failed(),所以我个人以为是Hotspot GC开发的同学忘记做这件事情了,只需要在gch->clear_incremental_collection_failed()后面调用新生代的clear_should_allocate_from_space()即可解决此类问题

结语

至此应该大家知道问题答案了,实际上是可能在from space里直接分配对象的,但是现在的实现可能存在一些问题会导致老生代GC变得频繁。

一起来学习吧:

PerfMa KO 系列课之 JVM 参数【Memory篇】

一次 Java 进程 OOM 的排查分析(glibc 篇)

Hotspot GC研发工程师也许漏掉了一块逻辑的更多相关文章

  1. Java研发工程师知识点总结

    Java研发工程师知识点总结 最近一次更新2017年12月08日 大纲 一.Java基础(语言.集合框架.OOP.设计模式等) 二.Java高级(JavaEE.框架.服务器.工具等) 三.多线程和并发 ...

  2. 源码分析HotSpot GC过程(三):TenuredGeneration的GC过程

    老年代TenuredGeneration所使用的垃圾回收算法是标记-压缩-清理算法.在回收阶段,将标记对象越过堆的空闲区移动到堆的另一端,所有被移动的对象的引用也会被更新指向新的位置.看起来像是把杂陈 ...

  3. 学生党如何拿到阿里技术offer: 《2016阿里巴巴校招内推offer之Java研发工程师(成功)》

    摘要: 这篇文章字字珠玑,这位面试的学长并非计算机相关专业,但是其技术功底足以使很多计算机专业的学生汗颜,这篇文章值得我们仔细品读,其逻辑条理清晰,问题把握透彻,语言表达精炼,为我们提供了宝贵的学习经 ...

  4. 2015年阿里实习生面试Java研发工程师 小记

    5月5日,广州,阿里实习生面试,Java研发工程师,完全被虐orz 几乎没有Java项目开发经验,接近零基础,去水了一发,毫无悬念的被刷了..RP也是杠杠的,准备过的题目一个都没被问到,算法题也是一条 ...

  5. 芒果TV招聘研发工程师(JAVA PYTHON),地点长沙

    长沙芒果TV招聘高级 JAVA Python 工程师,工作地点:湖南广电   有兴趣的邮件0xmalloc@gmail.com; zealotyin@qq.com 公司有一大批从北京上海一线互联网企业 ...

  6. 【转】Web前端研发工程师编程能力飞升之路

    分类: Javascript | 出自 海玉的博客 今天看到这篇文章.写的非常有意思.发现自己还有很长的一段路要走. [背景] 如果你是刚进入WEB前端研发领域,想试试这潭水有多深,看这篇文章吧: 如 ...

  7. 上海华魏光纤传感科技有限公司 招聘 《.NET研发工程师》

    代友招聘 <.NET研发工程师> **** 公司简介 **** 上海华魏光纤传感技术有限公司成立于2001年,注册资金1458.16万人民币,专业从事光纤传感技术的研究开发,为交通.市政等 ...

  8. Web前端研发工程师编程能力飞升之路

    今天看到这篇文章.写的非常有意思,于是转载了.看看我们都处于什么的阶段. [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧:如果你是做了两三年web产品前端研发,迷茫找不着 ...

  9. WEB前端研发工程师编程能力成长之路(1)(转)

    WEB前端研发工程师编程能力成长之路(1)   [背景] 如果你是刚进入WEB前端研发领域,想试试这潭水有多深,看这篇文章吧: 如果你是做了两三年WEB产品前端研发,迷茫找不着提高之路,看这篇文章吧: ...

随机推荐

  1. 题解:2018级算法第五次上机 C5-图2

    题目描述: 样例: 实现解释: 所有结点对最短路径的板子题 知识点: 寻找所有结点对最短路径,动态规划 坑点: 无坑,注意建边即可 使用的算法为floyd算法 按照程序顺序解释如下: 首先建图,以邻接 ...

  2. 【Hack.lu-2017】FlatScience

    信息: 题目来源:Hack.lu-2017 标签:SQL注入.源码泄露 解题过程 题目页面有多层,存在许多pdf文件,首先进行目录扫描: [TIME] => 2020-07-07 16:08:5 ...

  3. 数据可视化之PowerQuery篇(五)PowerQuery文本处理技巧:移除和提取

    https://zhuanlan.zhihu.com/p/64419762 每当拿到原始数据,不如意十有八九,快速准确的清洗数据也是必备技能,数据清洗正好是 PowerQuery 的强项,本文就来介绍 ...

  4. Java实现 LeetCode第30场双周赛 (题号5177,5445,5446,5447)

    这套题不算难,但是因为是昨天晚上太晚了,好久没有大晚上写过代码了,有点不适应,今天上午一看还是挺简单的 5177. 转变日期格式   给你一个字符串 date ,它的格式为 Day Month Yea ...

  5. bzoj3378[Usaco2004 Open]MooFest 狂欢节*

    bzoj3378[Usaco2004 Open]MooFest 狂欢节 题意: n只奶牛,第i只听力为vi,坐标为xi,两只奶牛聊天时音量是max(vi,vj)*abs(xi-xj).求n(n-1)/ ...

  6. GPO - Windows Server Update Services

    Windows Server Update Services Configuration Wizard: Approve procedure of these updates is very tiri ...

  7. Redis如何存储和计算一亿用户的活跃度

    1 前段时间,在网上看到一道面试题: 如何用redis存储统计1亿用户一年的登陆情况,并快速检索任意时间窗口内的活跃用户数量. 觉得很有意思,就仔细想了下 .并做了一系列实验,自己模拟了下 .还是有点 ...

  8. CF940E Cashback 线段树优化DP

    题目描述 Since you are the best Wraith King, Nizhniy Magazin «Mir» at the centre of Vinnytsia is offerin ...

  9. ant design pro 实战 : 使用 ztree

    应当指出,antd 是有 ztree 组件的,但是太简单,无法满足复杂的业务需求. 所以我还是决定使用zTree. 用 npm | cnpm 或者 yarn | tyarn 安装,这一步略. 在 js ...

  10. 简单分析 ztree 源码

    为了把 SVG标注 代码抽成一个库,我要学习一下 ztree 是怎么写的. 开始正文. 这只是一个很简单的版本,以后可能会详细分析... (function ($) { var settings = ...