4小时4面!Android 架构岗面经分享
作者:橘子没了
juejin.cn/post/7221131955202736183
前言
此次面试一共4面4小时,中间只有几分钟间隔。对持续的面试状态考验还是蛮大的。关于面试的心态,保持悲观的乐观主义心态比较好。面前做面试准备时保持悲观,尽可能的做足准备。面后积极做复盘,乐观的接受最终结果。
切忌急于下结论,哪怕面试当场明显感觉好或不好。快思考时我常会放大积极面信息而缩小负面影响,导致做了过于乐观的抉择,回来后或者隔一天以后再思考,这时候可以做到慢思考,通过复盘来下一个更为理智的决断。
一面:基础技术(JVM,多线程偏多)
问:说一下JVM的结构
说了堆,方法区,线程栈三个块的介绍。这里漏掉了说太快漏掉了程序计数器跟本地方法栈,但在面试官特地的问的时候也正确回答了作用。
问:volatile 的作用与实现原理
用于变量修改时在多线程场景下保持修改的可见性,但并不能完全解决多线程并发修改的问题。举例了两个线程访问 i++的例子。
问:那介绍一下为什么说 i++是两步操作
介绍了i++字节码指令执行顺序以及方法栈执行细节
问:Volatile 修饰的变量在修改时具体如何实现可见性的
这一步我直接回复不知道了,没有特地看过 volatile 修饰的字节码,不瞎说。面试官便给我进行了简单的介绍,我当时就想着回来一定要自己也看一看,之前为啥没看,哎。
首先在字节码中,针对Volatile修饰的变量会有一个 ACC_VOLATILE 标志:
可见性:当前线程修改后其他线程堆修改后的值立即可见,线程修改值之后立即写入到主存区,不用等到线程出栈的时候才同步到主存区。(线程工作区内存中保存的值要等待线程出栈时才写回主存区,在此之前其他线程对修改是不可见的) 顺序性:即读写的顺序性,而不会出现 读的过程中写入,或写入过程中被读取 不保证原子性:比如i++
// 读-写顺序性,假设有一个被 ACC_VOLATILE 标志修饰的 volatile 字段 v
// 线程 1
getfield v // 读取字段 v 的值
iconst_2 // 将常量值 2 压入操作数栈
putfield v // 将操作数栈顶的值存入字段 v 中
// 线程 2
getfield v // 读取字段 v 的值
//写-读顺序性,假设有一个被 ACC_VOLATILE 标志修饰的 volatile 字段 v
// 线程 1
iconst_1 // 将常量值 1 压入操作数栈
putfield v // 将操作数栈顶的值存入字段 v 中
// 线程 2
getfield v // 读取字段 v 的值
问:那如何保证原子性
加锁跟使用Atomic类
问:Atomic 是如何保证原子性的,或者说如何实现CAS的
这里太久没碰这块代码,听到CAS蒙了,问了一下原来是说CompareAndSet。不过这里依然是没准备,直接回答了未深入研究。
gpt:CAS底层采用CPU原子指令或锁机制来实现,多数情况采用cpu原子指令,通过硬件级别的操作来完成对一个内存位置的读写比较。
这个快确实深啊,而且这种信息不太容易记忆。作为一个了解性内容吧。并不会产生二次开发所以应用比原理要重要。
问:你刚讲到了堆,锁,那你了解过对象的 markword 吗,它里面有什么信息
markword 有了解,但是没有特别深。记得比较清楚的是有age 用于垃圾回收判断,有锁的标记位。
问:那对于偏向锁是如何转到轻量锁的
坦诚了一下想不起来,这里我自己虽然学习过,但是没作为重点知识准备。
markword 中32位中会有几位来标记锁信息,其中包含当前持锁的线程ID 分为 无锁状态(对象无锁),偏向锁(单线程访问有锁对象),轻量锁(多线程访问有锁对象),重量级锁(轻量级锁无法解决竞争问题时上升到重量级锁,借助操作系统完成锁机制)。这里又能展开,锁竞争原理,锁开销不同的原因。在竞争锁时,为获取到锁的线程会进行Spin(自旋,最大10次),在无阻塞情况下尝试获取锁,超过次数阈值后,膨胀为重量级锁,基于操作系统的锁机制,进行阻塞式等待锁的释放,减少自旋开销(开销具体是什么?不想挖了)
应用到代码里完成知识从理解到应用的闭环:
使用synchronized 修饰方法,类来设置轻量级锁 使用 object.lock()或者可重用锁,读写分离锁,都是重量级锁
问:说说 age在垃圾回收中如何应用
这里回答比较清晰,从垃圾回收分区到age增长到对象换内存区
问:handler消息机制
这部分主要是讲了 ThreadLocal 的特性,以及结合它如何完成多线程通信的。包括 messageQueue 的消息取出与执行方式。对于 native 层 nativePollOnce 机制直接回复了未深入。我也不打算深入,集中在应用层的使用上收益比较大。
问:app 启动流程,与启动优化
这部分比较熟,回答也还可以。整理过源码阅读笔记,启动优化经验也比较足。
问:TLS/TCP的 部分里拥塞控制跟流量控制 (部分没有回答上来)
传输数据时数据包是被切成小块的(减少重传次数),切多大则是根据下面的两个策略进行平衡的。 这在接受数据方,这部分是因为在做面试准备的时候没有刻意看,导致面试的时候没有结构化的进行表述。整体可以总结为在做数据传输时,每一个tcp链接都有窗口大小平衡每个tcp的的传输速率(分配到的带宽窗口),窗口大小自然是动态的,通过控制窗口大小避免单个tcp占用过大带宽,导致传输拥塞。 发送方会根据接收方允许的窗口大小,调整自己发送的数据包大小,避免拥塞,这一步则是流量控制。 日常开发中针对这个优化则是降低接口数据体量,做接口拆分,分批次请求等等。
问:Retrofit用过吧,说下他动态代理的实现原理
这里确实很深,我简单说了下自己学习掌握的原理概论与一些API与使用 ,因为这个要获取运行时字节码才可以搞明白。
面试官为我慷慨讲解了一些细节,没太记清楚,但我自己对于字节码理解还行,所以相对的给力一些临场反馈,全当学习了。当然,非常感谢他与我分享。就冲着些,这波面试已经不算白来了。
二面:TL
问:
组件化经验,实现方式 DevOps 搭建思路
这部分其实是在我的能力与他们目前需要最契合的部分,我也没有卖关子。直接用 ipad 连画带将,整个分享了一下。对就是分享了一下,结合团队技术能力,资源掌握情况,项目阶段等等给出整体的建设节奏。
问:
启动优化 字节码插桩 APP 打包流程
APP 打包流程这里整体流程没有少说,但是顺序是在面试官的提醒下纠正下调整的。不过我也先袒露了资源文件合并跟 javac 编译的顺序可能记错了。
问:线程池的的运行原理
这里确实大意了,核心线程,非核心线程,任务队列三个之间的扭转关系。其实很简单就是先入队再分配执行。
一个是之前学习是更多的是关注针对业务场景做配置,但是没有深入到源码去看。
问:对 IOS 的熟悉程度,主要是 CI 部分
整体上还是保持坦诚谦虚的态度。
问:动态Dex加载(插件化部分),加载Dex的类叫啥
整个面试里最尴尬的就这,我忘了!完全忘了,前两天才还开源的相关代码 ,就一个 DexClassLoader 愣是没想起来。
问:
分代垃圾回收的不同算法 什么对象会被回收
其实就是 GCRoot,这里没回答特别好,忘了 1-2 个比较重要的。
首先是存活的线程,被存活的线程引用的对象。其次还有系统 Class,被线程访问的方法内的局部变量,被当作锁或在执行 wait 或 notify 的对象。还有一些其他的记不住那么多了,主要是用太少了。
三面:HRD
问:
离职原因 对前两轮表现自我评价如何
他们两位在各自的领域展现的能力都非常出色,我对自己的整体评价不是特别好。但跟他们聊得蛮好,已经学到了很多知识,并且在后续沟通中对一些技术方案做了交换性讨论,这感觉非常好。
我又咨询了公司文化,公司历史。日常工作流程制度,绩效考核等信息。
这块相互交流了一些工作方式方法,大概了解公司目前的协作流程制度,可能是她很忙所以薪资部分还没聊就到下一面了。
四面:部门BOSS(管理技能与解决问题的闭环能力)
问:
如何做团队人员建设 参与极限开发时如何做管理,保证项目按时交付 从用户体验角度如何优化提及类型接口长时间的loading DevOps是如何建立的,做了哪些计划与安排 薪资期望(坦诚自己的一些预估,也表示愿意再聊,因为在目前这个薪资包范围下,小浮动我是不太在乎的)
这部分回答虽然是开放式的,但从一个管理问题出发,应该放在管理框架中系统性的进行回复,这样才能展现自己完整的管理经验。
团队scope要说清楚,以结果为导向的目标管理团队文化基调也应该展开说是如何建立起来的 人才盘点,根据什么盘点,如何确认招聘目标,招聘安排,面试安排,试用期安排,这都是自己做过的完整的流程
日常管理,人员安排,从知人善用出发,采用绩效考核,培训分享,以及自己在团队变大后的角色转变,团队成员单面能力超过我,我如何辅助他们做的更好,比如提拔为单方向负责人
项目管理,敏捷开发模式,需求评审,技术预研,工时审核,deadline模式下的区别管理 这中间会涉及到研发流程,CI等等,都可以提一下,有兴趣面试官自然会细问
自己在这个过程中做得比较好的就是带领团队整体完成从过程管理到目标管理的转变,取消了日报,改为了早晨共享今日todolist,完成目标管理方式落地
最后引出自己的底层管理思维:为团队成员服务,减少成员工作的干扰,建立团队与公司目标的链接,最后通过团队去拿结果
另外延伸聊到了通勤时间看书效率低,都喜欢看纸质书,公司同事周边租房的一些现状。
最后面试官送我到了电梯口,帮我按了电梯,我便主动握手告别,算是结束了今天长达4小时的4轮面试。
总结:乐观接受
java侧针对基础技术还是要做为重点准备,对准备的每个点做做自我穷问,能有效发现自己那块儿忘记深入。
Android侧 应用层知识不多,不需要花太多功夫,看看之前整理的文章就行
在DevOps侧要突出表现一些,多引导面试官了解这部分内容,本身自己对这块兴趣最大,思路比较完整。
虽然不一定100%能拿offer,但这次面试非常值,远超来回100多的车费了😄。
但是整体面下来节奏自己把握的还不错,自己掌握的东西基本都引导面试官进行了了解。针对面试没答上来的问题梳理下,觉得需要深入学的已经学习了,不需要深入学的暂时也不该花精力扎进去。
依然保持做一个悲观的乐观主义者吧~
-- END --
推荐阅读