Android 面试经验 - 大厂 OPPO 面
写在前面
一直有同学跟我反馈说,你能不能说说你的一些面试经验啥的,其实很多时候我是拒绝的,因为我们简历经历不一样问的问题也会不一样,且大厂面试光靠背几个面试题就想过还是比较难的。因此在这里提醒一下大家不要临时抱佛脚,你花几天能背下的东西,别人花几天一定能超过你的,但我们花几年沉淀的东西,人家花几个月就未必能赶上,希望大家不飞则已,一飞冲天。
说说当时面试的过程,是 boss 直聘 HR 推了简历给有关部门,简历通过后电话约的面试机会。当时约的是 10:30 的面试时间,所以只请了半天假。十点早早就到了华润大楼楼下,由于那个楼层有点复杂花了整整十几分钟才到 32 楼(是个食堂)。第一轮是两个面试官轮流问问题,第一面大约面了一个小时到了 11:40 渐渐有人吃饭了,撕了手机标签我就准备走了。这时两个面试官说你要不再等会,我打电话给我们老大,后来打电话又打不通就直接下去叫了,我就在食堂开始看着别人吃饭。大约等了十几分钟第二面的面试官把我叫到了 31 楼,也是两个面试官轮流问了大概一个小时,面完二面后就差不多到了下午一点,面试官说我带你去食堂吃个饭,吃完饭面试官帮我约了下午两点的 HR 面。感觉整个流程下来非常爽,总共三轮面试,两轮技术面(每轮2个面试官),一轮 HR 面。
技术一面
- mmap + native 日志优化?
讲了传统日志打印的两个性能问题,一个是反复操作文件描述符表,一个是反复进入内核态,然后讲了 mmap 的原理机制。
- 讲讲 Android 开机启动的流程
讲了一大堆,其中说到 ServiceManager 进程是用来管理系统服务的,面试官说你确定?不是 SystemServer 进程来管理系统服务的吗?讨论了一番面试官懵逼了,提到了 SystemUI 服务,提到了桌面进程,问到了怎么替换开机启动的动画?
- 系统是怎么帮我们启动找到桌面应用的
我说通过意图,他说怎么找到是哪个意图? 我说 PMS 会解析所有 apk 的 AndroidManifest.xml ,如果解析过会存到 package.xml 中不会反复解析,PMS 有了它就能找到了。
- 讲讲动态状态页的加载,为什么要这么弄?
我说为了减少 xml 解析和反射创建对象的时间,避免同时创建多个用不上的对象,我就写了个框架用代码动态添加的。这时面试官误解了我的意思,以为所有的界面都是用代码写的,那得多麻烦呀,后来解释清楚了。
- 讲讲页面的刷新机制,GPU 调试工具几个颜色值分别代表什么?
讲到了 Surface 底层管理的其实是 IBPQ , 讲了异步信号的由来是 SurfaceFlinger 由硬件和软件机制发出来的,讲了我们 app 界面绘制的内容是怎么提交传递到 SurfaceFlinger 的。GPU 调试工具几种颜色的意思也大概讲了下。
- 说说 ConcurrentHashMap 的实现原理说下
是线程安全的,实现原理采用的是分段锁。
- 你知道 okhttp 是怎么复用连接的吗?
这是个网络优化的问题,同一个 ip 同一个端口能复用一个连接,后面问道了 http 2.0 的多路复用,我说一个 tcp 可以多个请求,原理呢?我说不知道。后面让我说了下 https 。
-
数组和链表的区别说下
-
快排和递归
技术二面
- 讲一讲动态注册和静态注册
静态注册是通过包名和函数名去找方法,动态注册是通过注册方法表,其中还被问到了具体是调用哪个函数注册方法表。
- so 的加载流程是怎样的,生命周期是怎样的
这个要从 java 层去看源码分析,是从 ClassLoader 的 PathList 中去找到目标路径加载的,同时 so 是通过 mmap 加载映射到虚拟空间的。生命周期加载库和卸载库时分别调用 JNI_OnLoad 和 JNI_OnUnload() 方法。
- native 层怎么检测内存泄漏
我说按道理可以 hook 函数,开辟内存和释放内存的次数应该是一样的,如果不一样可以怀疑内存泄漏。面试官接着问有没有什么第三方工具或者库可以检测?我说我在公司其实也写的不多,不知道引擎组集成的是啥框架,主要擅长应用层开发。
- leakcanary 的原理,哪些对象可以用来做 gc-root
好,你说你主要擅长应用层开发,那 Java 层的内存泄漏怎么检测,我说我们用的 leakcanary,让我说说原理,说完原理又问我是不是所有对象泄漏 leakcanary 都能检测得到,他的引用链是怎么管理的?后面问到你刚说弱引用对象在 gc 的时候会被释放,那什么时候不会被释放?我这时懵逼了,其实就是有内存泄漏的时候不会被释放,我当时脑子短路了居然没反应过来。
- ui 怎么优化的?
我主要从底层讲了一下 UI 刷新机制的流程,又把一面的 SurfaceFlinger 底层机制讲了一遍,原理搞清了就可以做很多优化,巴拉巴拉说了一大堆,最后讲了怎么去监听 UI 卡顿。
- 线程耗时卡顿怎么监听的?
主要用工具去检测,当时只提到了 systrace + 函数插桩的方式。
-
说说你看的 Tinker 的原理?
-
你遇到的最难解决的问题?
我说我们公司项目没有采用动态加载框架,但是后面集成 U3D 项目需要动态加载,但只需要用到 so 和资源动态加载,功能上第三库也不支持我们的需求,我就自己硬着头皮看了各大版本的源码,支持动态修复替换加载 so 和 assets 资源动态修复加载,然后把具体的细节说了一遍。
- 常见数据结构你都熟悉哪些?不是本专业算法你是怎么学的?
数组,链表,堆,二叉树,队列,栈,平衡二叉树,红黑树,霍夫曼树,图。自己看书算法通过刷题,这里没具体问算法细节。
- 线上有人反馈问题你一般怎么处理的?
开发过程中记录关键日志,线上获取用户日志来分析。
个人体会
不用凡是都抱着得到的心态去做,就好比学习我就一定是为了进 BAT,如果是这样那当我们进了 BAT 又该如何,就好比死亡并不是代表生命的结束,学习这件事应该是终身的。只要我们能静下心来该来的自然会来,作人无甚高远事业,摆脱得俗情,便入名流;为学无甚增益工夫,减除得物累,便超圣境。
不要凡是都抱着利益的心态去做,一直以来我都是崇尚成就自己的同时去成就别人。只要自己不抱着利益的心态去做,那么便能拿得起放得下,当我想讲的时候便可以讲,不想讲的时候便可以不讲。过程中肯定会有各种疑问和怀疑,若坚持不了就放弃,但心中若有挂碍就铭记。
大家要记住凡事都只能靠自己,不要轻信某些培训机构谁谁是 BAT 大佬,谁又是华为出来的,作为过来人来看很多是为了营销, BAT 的要求绝对高于培训的那些知识。但倘若我们的知识体系的确还没有达到那个程度,肯定是可以考虑且选择的,只是我们自己要知道光学那些还不够,当然大家也不要相信我,凡事多问问自己的心。