移动开发最新搞懂Android应用启动过程,再也不怕面试官了,2024年最新开发岗位面试自我介绍

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

百万年薪必刷面试题

最全Android进阶学习视频

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

//ZygoteInit.java

public static void main(String argv[]) {

//Server类,封装了socket

ZygoteServer zygoteServer = new ZygoteServer();

//创建服务端socket,名字为socketName即zygote

zygoteServer.registerServerSocket(socketName);

//进入死循环,等待AMS发请求过来

zygoteServer.runSelectLoop(abiList);

}

看到ZygoteServer。

//ZygoteServer.java

void registerServerSocket(String socketName) {

int fileDesc;

//socket真正的名字被加了个前缀,即 “ANDROID_SOCKET_” + “zygote”

final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

String env = System.getenv(fullSocketName);

fileDesc = Integer.parseInt(env);

//创建文件描述符fd

FileDescriptor fd = new FileDescriptor();

fd.setInt$(fileDesc);

//创建LocalServerSocket对象

mServerSocket = new LocalServerSocket(fd);

}

void runSelectLoop(String abiList){

//进入死循环

while (true) {

for (int i = pollFds.length - 1; i >= 0; --i) {

if (i == 0) {

//…

} else {

//得到一个连接对象ZygoteConnection,调用他的runOnce

boolean done = peers.get(i).runOnce(this);

}

}

}

}

来到ZygoteConnection的runOnce。

boolean runOnce(ZygoteServer zygoteServer){

//读取socket请求的参数列表

String args[] = readArgumentList();

//创建应用进程

int pid = Zygote.forkAndSpecialize(…);

if (pid == 0) {

//如果是应用进程(Zygote fork出来的子进程),处理请求参数

handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

return true;

} else {

return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);

}

}

handleChildProc方法调用了ZygoteInit的zygoteInit方法,里边主要做了3件事:

  1. 启动binder线程池(后面分析)

  2. 读取请求参数拿到ActivityThread类并执行他的main函数,执行thread.attach告知AMS并回传自己的binder句柄

  3. 执行Looper.loop()启动消息循环(代码前面有)

这样应用进程就启动起来了。梳理一下:

下面看下binder线程池是怎么启动的。

启动binder线程池

Zygote的跨进程通信没有使用binder,而是socket,所以应用进程的binder机制不是继承而来,而是进程创建后自己启动的。

前边可知,Zygote收到socket请求后会得到一个ZygoteConnection,他的runOnce会调用handleChildProc。

//ZygoteConnection.java

private void handleChildProc(…){

ZygoteInit.zygoteInit(…);

}

//ZygoteInit.java

public static final void zygoteInit(…){

RuntimeInit.commonInit();

//进入native层

ZygoteInit.nativeZygoteInit();

RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);

}

来到AndroidRuntime.cpp:

//AndroidRuntime.cpp

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz){

gCurRuntime->onZygoteInit();

}

来到app_main.cpp:

//app_main.cpp

virtual void onZygoteInit() {

//获取单例

sp proc = ProcessState::self();

//在这里启动了binder线程池

proc->startThreadPool();

}

看下ProcessState.cpp:

//ProcessState.cpp

sp ProcessState::self()

{

//单例模式,返回ProcessState对象

if (gProcess != NULL) {

return gProcess;

}

gProcess = new ProcessState(“/dev/binder”);

return gProcess;

}

//ProcessState构造函数

ProcessState::ProcessState(const char *driver)
mDriverName(String8(driver))

, mDriverFD(open_driver(driver)) //打开binder驱动

,//…

{

if (mDriverFD >= 0) {

//mmap是一种内存映射文件的方法,把mDriverFD映射到当前的内存空间

mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,

MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

}

}

//启动了binder线程池

void ProcessState::startThreadPool()

{

if (!mThreadPoolStarted) {

mThreadPoolStarted = true;

spawnPooledThread(true);

}

}

void ProcessState::spawnPooledThread(bool isMain)

{

if (mThreadPoolStarted) {

//创建线程名字"Binder:KaTeX parse error: Expected group after '_' at position 6: {pid}_̲{自增数字}"

String8 name = makeBinderThreadName();

sp t = new PoolThread(isMain);

//运行binder线程

t->run(name.string());

}

}

ProcessState有两个宏定义值得注意一下:

//ProcessState.cpp

//一次Binder通信最大可以传输的大小是 1MB-4KB*2

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

//binder驱动的文件描述符fd被限制了最大线程数15

#define DEFAULT_MAX_BINDER_THREADS 15

我们看下binder线程PoolThread长啥样:

class PoolThread : public Thread {

public:

explicit PoolThread(bool isMain)
mIsMain(isMain){}

protected:

virtual bool threadLoop()

{ //把binder线程注册进binder驱动程序的线程池中

IPCThreadState::self()->joinThreadPool(mIsMain);

return false;

}

const bool mIsMain;

};

来到IPCThreadState.cpp:

//IPCThreadState.cpp

void IPCThreadState::joinThreadPool(bool isMain)

{

//向binder驱动写数据:进入死循环

mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

status_t result;

do {

//进入死循环,等待指令的到来

result = getAndExecuteCommand();

} while (result != -ECONNREFUSED && result != -EBADF);

//向binder驱动写数据:退出死循环

mOut.writeInt32(BC_EXIT_LOOPER);

}

status_t IPCThreadState::getAndExecuteCommand()

{

//从binder驱动读数据,得到指令

cmd = mIn.readInt32();

//执行指令

result = executeCommand(cmd);

return result;

}

梳理一下binder的启动过程:

  1. 打开binder驱动

  2. 映射内存,分配缓冲区

  3. 运行binder线程,进入死循环,等待指令

总结

综上,Android应用进程的启动可以总结成以下步骤:

  1. 点击Launcher桌面的App图标

  2. AMS发起socket请求

  3. Zygote进程接收请求并处理参数

  4. Zygote进程fork出应用进程,应用进程继承得到虚拟机实例

  5. 应用进程启动binder线程池、运行ActivityThread类的main函数、启动Looper循环

完整流程图:

面试前的知识梳理,储备提升

自己的知识准备得怎么样,这直接决定了你能否顺利通过一面和二面,所以在面试前来一个知识梳理,看需不需要提升自己的知识储备是很有必要的。

关于知识梳理,这里再分享一下我面试这段时间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)

  • **架构师筑基必备技能:**深入Java泛型+注解深入浅出+并发编程+数据传输与序列化+Java虚拟机原理+反射与类加载+动态代理+高效IO

  • **Android高级UI与FrameWork源码:**高级UI晋升+Framework内核解析+Android组件内核+数据持久化

  • **360°全方面性能调优:**设计思想与代码质量优化+程序性能优化+开发效率优化

  • **解读开源框架设计思想:**热修复设计+插件化框架解读+组件化框架设计+图片加载框架+网络访问框架设计+RXJava响应式编程框架设计+IOC架构设计+Android架构组件Jetpack

  • **NDK模块开发:**NDK基础知识体系+底层图片处理+音视频开发

  • **微信小程序:**小程序介绍+UI开发+API操作+微信对接

  • **Hybrid 开发与Flutter:**Html5项目实战+Flutter进阶

总结

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

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

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

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

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

[外链图片转存中…(img-opF8uQTh-1715461163124)]

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

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

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

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值