杭州某写字楼,安琪拉穿着新买的19.9的皮鞋走进玻璃隔间办公室,准备迎接一场新的表演。

面试官 :看你简历上有些熟悉JVM,是吧?

安琪拉:是的

面试官 :那你跟我讲讲堆内存的分区。

安琪拉:[心想]:这很easy嘛,来,算是回顾一下JVM的基础知识。

我们知道堆分为新生代和老年代,新生代就是我们说的Yong Generation,老年代是 Old Generation。

面试官 :然后呢?

安琪拉:然后什么?

面试官 :讲完啦?下面没有啦?新生代呢?

安琪拉:你想听你可以跟我说嘛,你不说我怎么知道你想听。

新生代又分为Eden区和Survivor区,Survivor由From区域和To区域组成,完整的内存结构,我给你画一下,别抽了,笔递给我一下,我画一下,如下图所示。

面试官 :哦,图可以,那为什么堆要分新生代和老年代呢?

安琪拉:当然是为了更有效的管理内存。

面试官 :怎么说?

安琪拉:假设一下,如果不分新老代,内存就一整块,垃圾收集器每次都要把那些长期存在的对象,和生命周期很短的对象放在一起回收,一般长生命周期的对象可能跟应用生命周期一致,你基本回收不掉的,比如Spring 框架里面的Bean管理相关的对象(ApplicationContext),整个应用运行期间都存在,这种一般经过几次回收最后都放在老年代,但是如果不区分新老代,每次都一起回收,性能消耗很大。

区分新老代之后,老年代放长期存活的对象,新生代就放生命周期短的对象,老年代对象很稳定,新生代回收不影响老年代,回收效率能大大提高。

面试官 :那为什么新生代还要分Eden、From、To区域呢?

安琪拉:[开始慢慢有点意思了]

首先大部分对象生命周期是很短的,如果新生代不分多个区域,新生代可能会有二种回收方案

第一种可能:每次回收都在新生代整块内存上进行,完整的垃圾回收过程分三步:

  1. 需要先找到需要清理的对象标记;

  2. 清理这些被标记的对象;

  3. 移动剩下的对象,对达到老年代晋升年龄的对象移动到老年代。

对象被回收掉后会产生很多内存碎片(被回收的对象很多),如果要解决内存碎片,需要移动剩下的对象(标记整理算法),整个回收流程效率很低。

第二种可能:如果没有Survivor区(From + To),Minor GC(新生代回收)过程中,存活的对象直接被送到老年代,这样的话老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC),Full GC频繁会影响程序的执行和响应速度。

新生代的回收叫Minor GC, 老年代的回收叫Major GC。

面试官 :为什么要设置两个Survivor区呢?From 和 To

安琪拉:我们来看一下, 如果只有一个Survivor区,新生代内存的回收流程。

我按照上面这张图画的讲,第一次Eden区域满了,内存回收很简单,直接把Eden区域存活对象放到Suvivor区域;

第二次内存回收,需要回收二个地方,Eden区域和Survivor区域。

  • 因为Survivor区域也会存活的对象需要被回收,对Survivor区要采用标记整理垃圾收集算法,(先标记需要清理的对象,然后回收,然后把剩下的存活对象放到一起);

  • Eden区域采用复制算法,把Eden区域存放的对象复制到Survivor区域,然后把整个Eden区清除。

看到网上有些文章说这里设置二个Survivor区域的原因是为了避免内存碎片,因为他假设第二次(以及后续)的回收,内存回收是先回收Eden区域,然后是Survivor区域,这样当然会有内存碎片,但是如果真是只有一个Survivor区域,垃圾回收设计者肯定是先回收Survivor区域,再回收Eden区域,等Survivor区回收整理好,再把Eden区存放对象搬到Survivor区,这样存活地址是连续的,没有内存碎片。所以真正的原因还是我下面说的效率问题。

面试官 :这样有什么问题呢?

安琪拉:这样做有几个问题:

  1. 经过几次回收之后,Survivor区域满了之后怎么办?直接搬到老年代?那老年代很快就爆炸了。搬到Eden区?那内存碎片产生了,可能Survivor区和Eden区回收完之后,还需要再整理一下内存去掉内存碎片,性能消耗也是很大的。

  2. 一般标记整理算法的性能消耗是比复制算法消耗要大的,尤其是在新生代98%的对象都是“朝生夕死”的,标记清楚的是98%的对象,剩下就2%对象,要整理内存,不然直接把这2%对象放到另一个地方,把整块内存清除,Eden整块内存清除效率很高的。

所以归根结底,二个Survivor区还是为了性能考虑,标记复制算法效率比标记整理效率高。

面试官 :那你跟我详细讲讲标记新生代除了Eden,另外采用二个Survivor区的标记复制算法。

安琪拉:新生代中的对象 98% 是“ 朝生夕死” 的, 所以并不需要按照 1: 1 的比例来划分Eden和Survivor的空间, 而是将新生代分为较大的一块Eden空间和两块较小的Survivor 空间,每次只使用 Eden 和 其中一块Survivor[0](From区域),留出Survivor[1](To区域)用来实现标记复制。

当回收时, 将 Eden 和 Survivor[0] 中还存活着的对象一次性地复制到另外一块 Survivor[1] (To)空间上, 最后清理掉 Eden 和 刚才用过的 Survivor 空间。

另外说明一点:From区域和To区域在每次Minor GC之后都会互转,From区域变成To区域,To区域变成From区域,这只是逻辑标识

HotSpot 虚拟机默认 将Eden 和 Survivor 的大小比例是 8: 1(CMS不适用), 也就是每次新生代中可用内存空间为整个新生代容量的 90%( 80%+ 10%),只有10%的内存会被“ 浪费”(一直有10%的内存(Survivor To区)不存东西)。

标记复制算法流程:

  1. Eden区域+Survivor From区满,进行存活对象标记,标记完,把存活对象复制到Survivor To区域;

  2. Survivor To区域变成From区域(一个逻辑标识),From区域变成To区域;

  3. 内存分配,继续步骤1,复制过程中有达到老年代晋升年龄(默认值15),移动到老年代。

面试官:刚才说了这么多,是不是来之前背题了?

安琪拉:【心想】回答不出来你说我对技术没追求,回答出来了你说我背题,WTF。。

耐心对面试官解释:怎么可能,我只不过是来之前把安琪拉的博客公众号上的文章都看了一遍,嘿嘿。

面试官:在哪看,你分享给我。

面试官:诶诶,还有老年代内存回收策略呢?还有标记整理算法呢?另外讲讲几种常见的垃圾回收器,CMS和G1。

安琪拉:不想讲了,累了,要不放在二面的时候讲吧。

面试官:没事,二面面试官还是我,你直接讲吧。

安琪拉:真不想讲了。

面试官:那今天先到这吧,回去等通知,您出了这个门左拐。

文章来源于读者的提问。

面试官问为什么新生代不用标记清除算法相关推荐

  1. 【阿里二面】面试官问为什么新生代不用标记清除算法

    杭州某写字楼,安琪拉穿着新买的19.9的皮鞋走进玻璃隔间办公室,准备迎接一场新的表演. 面试官 :看你简历上有些熟悉JVM,是吧? 安琪拉:是的 面试官 :那你跟我讲讲堆内存的分区. 安琪拉:[心想] ...

  2. 看完这篇,我再也不怕面试官问垃圾收集了

    看完这篇,我再也不怕面试官问垃圾收集了 说在前面:本文的篇幅较长,看本文的时候最好先去上个厕所,先准备好一杯枸杞茶,慢慢品,本文将会讲解三种垃圾收集算法:标记-清除.复制.标记-整理算法,以及各种成熟 ...

  3. 大叔手记(10):别再让面试官问你单例

    大叔手记(10):别再让面试官问你单例(暨6种实现方式让你堵住面试官的嘴) ... 2012-2-19 09:03| 发布者: benben| 查看: 283| 评论: 0 摘要: 引子经常从Recr ...

  4. 已经成功拿到了几个offer的我来告诉你,Android面试官问的一些问题,看完这一篇就没有拿不到的offer

    前言 我是2020年毕业于中南大学的计算机学院的,大家可以叫我小吴,我嘞毕业之后在华为实习了差不多一年多,一直都从事着Android开发. 然后2021年的时候因为我自己的一些原因打算离职到外面看看, ...

  5. 面试官问我Java8~14的有哪些重要的新特性,我哭了~~~

    大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成.Java 8新特性见这里:Java8新特性最佳指南 . Guide 哥:别人家的特性都用了几年了,我 Jav ...

  6. 面试官问你GC怎么调优?思路是什么呀?我直接把这篇文章甩到面试官脸上

    有学过JVM垃圾回收机制的小伙伴肯定了解过CG调优,当面试官问到这个问题时,相信很多小伙伴第一时间想到的就是调节几个参数,调节一下分代的大小.简单的可以用这么一句话概括,水多了加面,面多了加水.十分形 ...

  7. 面试官问:数据库 delete 表数据,磁盘空间还是被一直占用,为什么?

    以下文章来源方志朋的博客,回复"666"获面试宝典 最近有个上位机获取下位机上报数据的项目,由于上报频率比较频繁且数据量大,导致数据增长过快,磁盘占用多. 为了节约成本,定期进行数 ...

  8. 面试官问:Kafka 会不会丢消息?怎么处理的?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Kafka存在丢消息的问题,消息丢失会发生在Broker, ...

  9. 当面试官问我ArrayList和LinkedList哪个更占空间时,我这么答让他眼前一亮

    前言 今天介绍一下Java的两个集合类,ArrayList和LinkedList,这两个集合的知识点几乎可以说面试必问的. 对于这两个集合类,相信大家都不陌生,ArrayList可以说是日常开发中用的 ...

最新文章

  1. CV之detectron2:detectron2安装过程记录
  2. 【十大经典数据挖掘算法】Naïve Bayes
  3. Python学习笔记:TypeError: not all arguments converted during string formatting
  4. 转载:实用 FRIDA 进阶 --- objection :内存漫游、hook anywhere、抓包
  5. 【JZOJ3885】【长郡NOIP2014模拟10.22】搞笑的代码
  6. SOPC自定义外设(IP)的地址对齐
  7. 2019 年互联网人才招聘报告:Java 吃香,算法工程师紧缺,今日头条崛起!
  8. day_05、内置函数、匿名函数
  9. IntelliJ IDEA多屏后窗口不显示问题解决(用工具一键解决)
  10. 【硬币识别】基于matlab形态学硬币计数【含Matlab源码 683期】
  11. 单片机PWM舵机控制原理
  12. 考研日语线上笔记(六):完型专项篇
  13. MYSQL时间函数之NOW()
  14. 虚拟DOM和deff算法
  15. 千万不要用memset函数对二维数组进行初始化
  16. 拉线传感器的数显仪表在测量中起到多大的作用
  17. 基于ROS的18届中航杯比赛流程实现
  18. 云计算概念 IaaS PaaS SaaS
  19. SwiftUI iOS 完整项目之基于CoreData构建购物计划App(教程含源码App Store上线app)
  20. Python网络爬虫之HTTP原理

热门文章

  1. Fedora中安装 Shutter步骤介绍
  2. 如何在Ubuntu Linux上开采以太坊?
  3. gbdt 算法比随机森林容易_机器学习(七)——Adaboost和梯度提升树GBDT
  4. 对‘pthread_create’未定义的引用_深入浅出 C++ 11 右值引用
  5. 如何实现java虚拟机的优化_Java虚拟机JVM优化实战的过程全记录
  6. Codeforces Round #704 (Div. 2)(A ~ E)5题全 超高质量题解【每日亿题2 / 23】
  7. AcWing 734. 能量石 (01背包)+(贪心 - 领项交换)
  8. 幸运数字Ⅱ(树型结构构造答案,打表)难度⭐⭐
  9. mysql 并发 参数_Mysql并发参数调整
  10. 7-5 符号配对 (20 分)