到今年7月,我已经工作了整整3年!记得还是2017年的夏天,我脱下了属于大学时代的学位服,告别我的整个学生时代,当我找到第一份正式的工作时,就已经宣布我成为正式的上班族了!那个朝气蓬勃的时代、也是一个属于青春的年代。现在回味、无比悠长。
原谅我矫情了一会儿,现在进入正题。想知道阿里面了5次,腾讯面了4次的我,为什么会入职字节跳动吗?看官,请你们接着往下看。
9面大厂的原因
我相信每一位软件开发的毕业生都梦想着进入像BAT这样一线大厂,你们都想着进入当然我也不例外,谁叫我们都是“同道中人”呢!
先说说我吧,虽然我不喜欢别人夸但是你们夸我还是有一点小骄傲的。双非一本毕业,虽然谈不上多么厉害但是也还行,别说读研我是真的不喜欢读书,读研天天要背英语单词难道你们不觉得烦吗?我比较喜欢有逻辑性的事物,因为这样在之后的大厂面试中算法题基本都答对了。
我吧,接触编程接触的比较早,在高一的时候因为我哥给我带了一本自学C语言的书,我便开始沉迷在编程的海洋里,一蹶不振。到现在那本书我还没有扔掉,现在有时间的时候都会看一看,不过现在看来里面的知识点太少了,适合刚起步的新手学习。对了这本书叫《C primer plus》,安利一下。
因为高中三年都热爱着编程,所以我高考完以后报考的志愿只能是计算机这一方向,别人说大学生活都是丰富多彩的,我也信了高中老师的鬼话,说什么高中三年不要玩,好好学习等到上了大学随便你玩,老师都不带管你的。以至于到现在都还没有女朋友,真气死我了...
大学四年中,我自学过Java、Andorid、C++,到后来火热的GO语言、AI,也有一定的了解,却因为大学老师的一段话走上了APP的开发之路,因为当年抖音的爆火,无数短视频APP横空出世,他说:将来做Android的程序员肯定特别吃香,听了老头这话一入坑便是三年。
虽然现在也挺好,在字节能到税后34K,但是我还是觉得,程序员需要的不是行情行业,需要的是实力和技术,只要你有硬实力,无论市场行情怎样,走到哪都会公司企业接纳你。内推不就是一个很好例子吗?
5面阿里,4面腾讯的心路历程
阿里和腾讯和字节一直是我追求目标,其实毕业前,我并没有找到心仪的工作,只是找到了一家小型互联网公司做Android开发(当然,是在面试完腾讯和阿里之后我才明白了我自身实力的不足)。
但是咱不能放弃,一次不行还有第二次,两次不行还有无数次。起码我得进他们的研发部看看他们的大牛到底有多厉害才能进得去那样的大厂?
于是,我开始我的三年面试大厂之路;
三年,我卡死在无数面试题之下,挫败了我也成就了我
我这个人最好的好处就是会在失败中总结,面试遇到不会的题目我会在心中记下,面试结束以后再网上找答案,在记录在我自己的学习笔记中。
比如像Android的音视频,UI线程、view分发反向制约的方法、Future和microtask执行顺序,Java的对象锁和类锁、生产者消费者(非阻塞式)我都会记下来。这也为我之后成功入职字节跳动做好了铺垫。
一面(2018年10月秋招)
简单介绍项目
了解哪些数据结构
了解哪些排序算法
堆排序
LinkedList与ArrayList;HashMap扩容 ConcurrentHashMap
TCP与UDP,区别及运用场景
http是用的TCP还是UDP
http与https的区别
JVM内存模型(Static方法在哪个区)
Activity生命周期,Activity启动模式,Handler源码
旋转数组
二面(2019年3月春招)
final、finally、finalize的区别
抽象类的成员变量与成员方法的继承
union与union all的区别
MySQL的索引的实现
B+树查找的时间复杂度,数据结构
在浏览器输入网址敲回车后经历了什么
三次握手
https的加密流程
对称加密与非对称加密原理(RSA、AES)
手撕DCL单例
还了解什么设计模式
三面(2019年四月春招)
动态代理的方法怎么初始化的
cglib动态代理
三个线程wait,唤醒情况是什么样的
最终是谁持有的activity,handler内存泄露(内存泄漏这点真的是无比幸运,刚好找到的视频里面讲过)
handler的sendmessage和postdelay的区别
arraylist和hashmap的区别,为什么取数快
差不多重复的和模糊的
四面(2019年9月秋招)
stringbuilder 和stringbuffer区别
lock和syncrognized原理区别,适合什么场景。
实现生产者,消费者
handler原理,是如何实现延时的。
一个activity启动另外一个activity的生命周期。
反转链表
归并排序
快速排序
五面(2020年5月春招)
抽象类和接口解释一下。
讲讲类的加载机制。
jvm的内存回收机制,那你了解哪些内存回收算法。主要用的那个算法。
抽象类和接口的区别。
Activity有哪些启动模式
Fragment的生命周期和Activity有哪些不同,执行顺序解释一下。(这个回答的有点迷,只能说大体是那么一回事)
线程和服务的区别,解释一下。
事件分发机制讲解一下,view中有个onFilterTouchEventForSecurity还是啥,小哥哥说是view中独有的一个方法,你了解吗?(英语水平不过关,没听清是啥方法,表示不清楚。)
充值模块如何进行的封装
handler的机制讲解一下。
模板方法讲解一下(脑袋抽了,记不起来)
如何保证应用的安全性,做了哪些处理。
加固的原理了解嘛。
腾讯5面面经
一面
- mmap + native 日志优化?
讲了传统日志打印的两个性能问题,一个是反复操作文件描述符表,一个是反复进入内核态,然后讲了 mmap 的原理机制。
- 广播和 EventBus 的区别?
说 EventBus 的实现原理是基于反射,里面管理了两张表,且代码之间关联性不大不易于维护,EventBus 不支持跨进程通信,被面试官反问你确定不支持跨进程?我说我的看的源码是不支持,面试官说那好吧。
- 常用设计模式你了解哪些?
我开始巴拉巴拉说了一大堆,其中说到了装饰设计模式,被面试官打断了,请你具体说说装饰设计模式。
- 跨进程通信有哪些?
管道,信号,信号量,文件,本地套接字,共享内存,binder 驱动
- 简单讲讲 binder 驱动吧?
从 Java 层来看就像访问本地接口一样,客户端基于 BinderProxy 服务端基于 IBinder 对象,从 native 层来看来看客户端基于 BpBinder 到 ICPThreadState 到 binder 驱动,服务端由 binder 驱动唤醒 IPCThreadSate 到 BbBinder 。然后又讲了虚拟内存、物理内存和内存映射,跨进程通信的原理是要基于内核的, 当我讲到 binder_open 、binder_mmap 和 binder_ioctl 是被面试官打断了,估计是怕我讲太久了。
- 跨进程传递大内存数据如何做?
我说 binder 肯定是不行的,因为映射的最大内存只有 1M-8K,可以采用 binder + 匿名共享内存的形式,像跨进程传递大的 bitmap 需要打开系统底层的 ashmem 机制。
- 说说 ConcurrentHashMap 的实现原理说下,初始化大小是多少?
是线程安全的,实现原理采用的是分段锁,初始化大小是 16 ,必须是 2 的幂次。
- 启动优化怎么优化?
我说了关键优化 Application ,被面试官打断了,说大家都能想到的东西你不要说了,我想听的是你能不能站在系统的角度去做一些优化,我提到了优化包体积大小能优化启动速度,优化 dex 分包能优化启动速度,可以参考最新的华为方舟编译器等等。
- 你写的 rxpay 和 rxlogin 具体怎么实现的?
一般我们集成第三方登录和第三方支付 SDK 都需要监听 onActivityResult 方法,我是参考了 RxPermission 的实现方案添加了透明 Activity 。
- kotlin + fullter 方面的
二面
单例设计模式都写写,静态内部类是怎么保证线程安全的?
synchronized 底层实现原理,ReentrantLock 公平锁与非公平锁。
主线程等待所有线程执行完毕,再执行某个特定任务怎么实现?原理和源码看过没?
自定义 view 的一般流程,要注意些什么如何优化,点击事件和长按时间分别是怎么实现的?
四种启动模式,在源码分析中的原理是怎样的?
讲讲 bindService 的过程,你当初是怎么优化后台服务进程的?
开发中你都用到了哪些设计模式?说说当时具体的场景。为什么你要用方法工厂,另外两种呢?
RxJava 在使用过程中碰到了某些不友好的错误一般怎么解决?发现了内存泄露一般怎么解决分析,有没有碰到过系统服务内存泄露的问题?
你们用的 okhttp ?那你有没有做过一些网络优化呢?比如弱网环境。
给你个数 1 吧,比如 1000011 里面有几个 1 ?
快排了解不?最坏的情况是怎样?如果有大量重复数据怎么优化?
三面
讲讲 handler 的底层实现原理? 这么简单?问到碗里来了,后面渐渐说到延迟消息是 nativePollOnce 来处理的,在 6.0 以上用的是 epoll 方式来监听文件描述符。接着问道了为什么要用这种方案?它跟 poll 和 select 比起来有哪些优势?它是怎么监听的你看过它的内部实现原理没?反正感觉很难受了。
说说你做的日志记录优化? 把第一轮面试的又讲了一通,你在每个文件的最后写入了当前内容的大小,你有没有想过如果文件被破坏的情况?这种异常情况怎么处理?后面还问到了加密和压缩。
你看过 binder 驱动的源码,说说他的内存映射过程,说说客户端等待服务端处理返回的流程,如果要跨进程传递大内存数据你具体会怎么做?简单写一写吧。
在公司做过哪些优化? 内存优化,启动优化,网络优化,包体积优化,具体说说包体积优化。我提到了包体积优化不仅仅是优化了包的大小,包体积太大从安装的那一刻开始,我们的应用就可能比较慢了,因为 pms 会去拷贝解压解析我们的 apk 安装文件,会去优化我们的 dex 等等,包体积太大还会影响我们的启动速度。然后就巴拉巴拉说具体怎么做,问到了为啥混淆资源能减少包体积大小?你当时优化的时候效果是怎样的减少了多少?
开发过程中遇到的一些最难解决的问题? 提到了动态修复替换加载 so ,那你知道怎么修复 class 吗?怎么修复资源呢?后面又聊到了插件化,提到了 360 用的是借尸还魂,那如果我们在插件的 Androidmanifest.xml 中注册了其它属性该怎么解决,资源方面怎么处理?
四面
- 先谈谈自己的项目
远程数据库传输图片到app端,我们当时将图片转换成base64存在数据库中,然后传到app端,app解析base64获得bitmap,直接显示然后面试官疯狂diss 为什么要将图片转成base64再传(二面也diss这个,问是否可以直接传图片地址)
讲一下http连接的框架
retrofit原理
什么是动态代理
自定义view
继承viewGroup的情况
activity的生命周期
对handler机制的了解
字节跳动面试题
一面
Jvm虚拟机
messageQueue会不会阻塞ui线程
对象锁和类锁
之字形打印树
还有其他的记不清了,主要是我对二面印象太深刻了
二面
dart是值传递还是引用传递、
Widget和element和RenderObject之间的关系
widget的root节点
mixin extends implement之间的关系
jvm内存模型
Future和microtask执行顺序
dart中…的用法
await for
三面
linux网络模型
b+树
阻塞队列
redis和MongoDB的区别。几个概念对比,还有底层实现。
算法题: mergeksortedlist,时间复杂度如何?
HashMap 如果一直 put 元素会怎么样?hashcode 全都相同如何?equals方法都相同 如何?
所以的面试题和答案都被我整理成PDF,这也为我入职字节跳动提供的保证,近期需要面试的,需要面试题参考的小伙伴(Github领取)PDF资料
文末
最后希望小伙伴们都能有个好的归宿,找到高薪的工作,拿到自己满意的offer。一起朝着大厂努力前进,共勉!喜欢的小伙伴可以拿出自己的小手指点个赞哟(#.#)