java 解析安卓应用,深入理解Android 卷1:Zygote进入java

1.引言

上节记录到zygote进程的产生哪里,zygote是进入Java层的入口。下面就按照书上,博客上写的,结合源码看看是不是那么回事。最后会打印log看看究竟,个人认为只需要吧每个流程能在大脑中形成一个完整的回路就行,不必搞懂代码的具体实现。

2.app_main.cpp

Zygote相关的代码在app_main.cpp中,按照调用流程,结合源码看一遍是不是那么回事。

app_main.cpp中 int main()方法有一段代码很重要,这段代码就能进入java层。

e3db4c11be73

image.png

AppRuntime 继承AndroidRuntime

e3db4c11be73

image.png

AppRuntime的调用:

e3db4c11be73

image.png

e3db4c11be73

image.png

start方法做了三件事:

1.初始化虚拟机,为进入java层做准备

2.注册jni函数。这句话可能不理解。这么说吧,Android系统本身有很多地方都是采用了jni。最常见

env->FindClass .没有这步注册动作,就没得这个api

3.通过反射调用ZygoteInit.java

初始化jvm

e3db4c11be73

image.png

注册jni函数

e3db4c11be73

image.png

反射调用java代码,进入java世界

e3db4c11be73

image.png

从代码片段可以看出调用的事main方法,且该方法还是一个静态的。进入ZygoteInit看看是否有这个方法。

e3db4c11be73

image.png

看到main()方法的确是有的并且还是一个static。

3.ZygoteInit.java

这个java层入口。按照书上说的,下面标注的是很重要的5个步骤。

e3db4c11be73

image.png

3.1 registerZygoteSocket

e3db4c11be73

image.png

registerZygoteSocket函数,这个函数其实很简单,就是创建了一个服务端的socket,并赋值给全局变量sServerSocket。那么这个服务端的socket具体要接受什么消息?当请求新建一个进程的时候,就会被这个socket接收到请求,然后就被处理。

3.2 preload()

e3db4c11be73

image.png

3.3 gcAndFinalize()

e3db4c11be73

image.png

3.4 startSystemServer

系统初始化到这里之后,系统中已经有3个进程了,最开始的init,zygote和zygote分裂出来的system_server。system_server部门我们以后再看,接着看zygote的执行。

e3db4c11be73

3.5 runSelectLoop

runSelectLoop函数的逻辑比较简单,主要有两点:

1、 处理客户端的连接和请求。其中客户端在zygote进程中使用ZygoteConnection对象表示。

2、 客户的请求有ZygoteConnection的runOnce来处理。

e3db4c11be73

image.png

4 SystemServer进程的作用

看如下代码:

startSystemServer()中有一个handlerSystemServerProcess()方法。顾名思义处理系统Server过程的方法。ActivityManagerService,WindowManagerService这些服务都是SystemServer进程处理的

handlerSystemServerProcess

e3db4c11be73

image.png

RuntimeInit.zygoteInit()通过抛出异常

e3db4c11be73

image.png

nativeZygoteInit()最后调用的是:

e3db4c11be73

image.png

applicationInit里面有一个invokeStaticMain方法,该方法通过传入的className,反射得到Method,然后抛出异常,其中参数m 就是className的Main方法,并且异常被ZygoteInit.main的catch捕捉到(实际上是android.app.ActivityThread类的main函数)。

e3db4c11be73

ZygoteInit捕捉异常:

e3db4c11be73

image.png

caller.run()通过这种方式间接性的调用了,SystemServer的main函数。

e3db4c11be73

5. 应用打开过程

打开一个应用相当于是开启了一个进程,这个流程是怎样执行的呢?

解析:

ActivityManagerService将请求发送给zygote进程后, 就轮到zygote进程处理消息了。通过分析zygote进程的启动流程,我们已经知道zygote进程收到请求后,将执行ZygoteConnection的runOnce函数。

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {

ArrayList fds = new ArrayList();

ArrayList peers = new ArrayList();

......

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

.........

if (i == 0) {

ZygoteConnection newPeer = acceptCommandPeer(abiList);

peers.add(newPeer);

fds.add(newPeer.getFileDesciptor());

} else {

//处理请求

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

if (done) {

peers.remove(i);

fds.remove(i);

}

}

}

............

}

接下来,我们看看函数runOnce的实际操作

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

//解析传入的参数

........

try {

.......

//与启动SystemServer进程一样,最终也会通过native函数fork,并配置进程的参数

pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir);

} catch (ErrnoException ex) {

.......

} catch (IllegalArgumentException ex) {

.......

} catch (ZygoteSecurityException ex) {

.......

}

try {

if (pid == 0) {

// 子进程创建成功

IoUtils.closeQuietly(serverPipeFd);

serverPipeFd = null;

//子进程根据参数利用handleChildProc作进一步处理

handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

// should never get here, the child is expected to either

// throw ZygoteInit.MethodAndArgsCaller or exec().

return true;

} else {

// in parent...pid of < 0 means failure 创建失败

IoUtils.closeQuietly(childPipeFd);

childPipeFd = null;

//父进程进行一些后续操作,例如清理工作等

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

}

} finally {

IoUtils.closeQuietly(childPipeFd);

IoUtils.closeQuietly(serverPipeFd);

}

}

最后,我们看看handlehandleChildProc:

private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {

//关闭fork过来的zygote server socket

closeSocket();

ZygoteInit.closeServerSocket();

//处理参数

........

if (parsedArgs.invokeWith != null) {

WrapperInit.execApplication(.....)

} else {

//完成进程的初始化,然后抛异常

RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */);

}

}

从上面的代码可以看出,函数handleChildProc最终还是会调用Runtime的zygoteInit。

如同SystemServer进程一样,普通进程也会进行一些初始化,建立binder通信后,抛出异常,最终由ZygoteInit.java捕获异常,然后反射启动对应类的main函数(实际上是android.app.ActivityThread类的main函数)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值