2024AndroidBAT-字节跳动74道高级面试第二篇,爆赞

##阿里巴巴–Android(虚拟机)内存模型

本专栏专注分享大型Bat面试知识,后续会持续更新,喜欢的话麻烦点击一个关注

从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线。

Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆。 堆是运行时数据区域,所有类实例和数组的内存均从此处分配。 非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。

简言之,Java程序内存主要(这里强调主要二字)分两部分,堆和非堆。大家一般new的对象和数组都是在堆中的,而GC主要回收的内存也是这块堆内存。

配一张示意图总结一下:

堆内存(Heap Memory): 存放Java对象 非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data 其它(Other): 存放JVM 自身代码等


###一.堆内存模型
既然重点是堆内存,我们就再看看堆的内存模型。

堆内存由垃圾回收器的自动内存管理系统回收。 堆内存分为两大部分:新生代和老年代。比例为1:2。 老年代主要存放应用程序中生命周期长的存活对象。 新生代又分为三个部分:一个Eden区和两个Survivor区,比例为8:1:1。 Eden区存放新生的对象。 Survivor存放每次垃圾回收后存活的对象。

看晕了吧,关注这几个问题:

1.为什么要分新生代和老年代?
2.新生代为什么分一个Eden区和两个Survivor区?
3.一个Eden区和两个Survivor区的比例为什么是8:1:1?

现在还不能解释为什么,但这几个问题都是垃圾回收机制所采用的算法决定的。 所以问题转化为,是何种算法?为什么要采用此种算法?

###二.可回收对象的判定
讲算法之前,我们先要搞清楚一个问题,什么样的对象是垃圾(无用对象),需要被回收? 目前市面上有两种算法用来判定一个对象是否为垃圾。

1. 引用计数算法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的

objective-c用的就是这种算法。 缺点是很难处理循环引用,比如图中相互引用的两个对象则无法释放。 这个缺点很致命,有人可能会问,那objective-c不是用的好好的吗? 我个人并没有觉得objective-c好好的处理了这个循环引用问题,它其实是把这个问题抛给了开发者。

2. 可达性分析算法(根搜索算法)

为了解决上面的循环引用问题,Java采用了一种新的算法:可达性分析算法。 从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。 [图片上传失败…(image-756421-1562504082698)] OK,即使循环引用了,只要没有被GC Roots引用了依然会被回收,完美! 但是,这个GC Roots的定义就要考究了,Java语言定义了如下GC Roots对象:

虚拟机栈(帧栈中的本地变量表)中引用的对象。 方法区中静态属性引用的对象。 方法区中常量引用的对象。 本地方法栈中JNI引用的对象。

Stop The World

有了上面的垃圾对象的判定,我们还要考虑一个问题,请大家做好心里准备,那就是Stop The World。 因为垃圾回收的时候,需要整个的引用状态保持不变,否则判定是判定垃圾,等我稍后回收的时候它又被引用了,这就全乱套了。所以,GC的时候,其他所有的程序执行处于暂停状态,卡住了。 幸运的是,这个卡顿是非常短(尤其是新生代),对程序的影响微乎其微 (关于其他GC比如并发GC之类的,在此不讨论)。 所以GC的卡顿问题由此而来,也是情有可原,暂时无可避免。

###三.几种垃圾回收算法

有了上面两个大基础,我们的GC才能开始。 那么问题来了,已经知道哪些是垃圾对象了,怎么回收呢?目前主流有以下几种算法。 PS:大家可以先猜猜Java虚拟机(这里默认指Hotspot)采用的是那种算法,…,答对了,是分代回收算法,现在是不是明白了前面堆内存为什么要分新生代和老年代了吧。但是即使猜对了,也要看其他几种算法哦,不然不要说我没提醒你,你会直接看不懂分代回收算法的。

1. 标记清除算法 (Mark-Sweep)

标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。 优点是简单,容易实现。 缺点是容易产生内存碎片,碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作。 示意图如下(不用我解说了吧):

2. 复制算法 (Copying)

复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。 优缺点就是,实现简单,运行高效且不容易产生内存碎片,但是却对内存空间的使用做出了高昂的代价,因为能够使用的内存缩减到原来的一半。 从算法原理我们可以看出,Copying算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很多,那么Copying算法的效率将会大大降低。 示意图如下(不用我解说了吧):

3. 标记整理算法 (Mark-Compact)

该算法标记阶段和Mark-Sweep一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。 所以,特别适用于存活对象多,回收对象少的情况下。 示意图如下(不用我解说了吧):

4. 分代回收算法

分代回收算法其实不算一种新的算法,而是根据复制算法和标记整理算法的的特点综合而成。这种综合是考虑到java的语言特性的。 这里重复一下两种老算法的适用场景:

复制算法:适用于存活对象很少。回收对象多 标记整理算法: 适用用于存活对象多,回收对象少

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。


以上分享【Android开发中高级必知必会核心知识笔记】七大模块整套学习资料均免费分享,需要的小伙伴,我已经上传到GitHub了,大家自取就可以了。白嫖可以,别忘了给我点个关注哈。

【Android开发中高级必知必会核心知识笔记】

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值