简述
我们知道Android系统已经为我们开发者模糊了进程的概念,我们甚至感受不到进程的存在,但是如果要深入了解Android系统就需要了解进程在Android中如何创建以及模糊的,我们今天的主题就是来探讨从APP的角度,进程是如何创建的。
概念储备
1.进程&线程
官方解释
- 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
- 线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。
翻译解释
可能上面的文字,我们并不知道说的什么,那下面我们就把这些翻译一下:
- 进程就是计算机独立分配资源的最小单位,资源就是那些变量乱七八糟使用的内存啊,cpu的调度呀等。
- 线程就是在进程中再次分出来相对独立可调度执行的单位,也就是一个进程内部可以包含多个线程,线程可以独立调度cpu的分配。
2.涉及Android中的进程&线程
- SystemServer进程
- Zygote进程
大概过程是:
app进程如果从桌面启动的话,发起的是Lacuncher所在进程,然后通过Binder调用到AMS,通过AMS的调用最后使用socket给zygote进程,zygote中有个循环,一直在读取socket的链接资源当读取到要创建进程的时候,则会fork()子进程,完了就会在新的进程中去创建一些Android系统的环境,所以最后走到ActivityThread.main()
发起环节
发起环节,主要是由于发起进程方,通过四大组件拉起进程方式是通过Binder调用AMS中,AMS最后会通过Process.java和Zygote通信创建进程,所以直接看Process.java
1.1 Process.start()
Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
//[1.2]
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException("");
}
}
1.2 Process.startViaZygote()
Process.java
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//[1.3][1.2]
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
1.2 Process.openZygoteSocketIfNeeded()
Process.java
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
//向主zygote发起connect()操作
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
...
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
//当主zygote没能匹配成功,则采用第二个zygote,发起connect()操作
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
...
}
这里我们已经看出来zygoteSendArgsAndGetResult()
这个方法的预谋,这个方法主要就是进行socket链接操作并且获取流。
1.3 Process.zygoteSendArgsAndGetResult()
Process.java
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
ProcessStartResult result = new ProcessStartResult();
//等待socket服务端(即zygote)返回新创建的进程pid;
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
看到这里已经出现了socket对流的操作,读和写,具体就是将数据封装到集合中,然后将几个一个个写入流中,最后阻塞进行等待。其实这里谷歌工程师也意识到有可能创建进程一直卡死到zygote哪里,并写入读的流,所以他们给这里说可能会加入时间判断。
这里还需注意的事情有:
- ProcessStartResult对象
- zygoteState:这个是通过1.2返回的链接对象,将socket链接的信息封装在zygoteState这个对象中
创建环节
这里是通过Zygote进程进行创建的,Zygote进程来自于init进程,init进程这里不说,总之init进程创建Zygote进程之后就进入到了java世界,这个java世界进行创建进程了,但是怎么给空荡荡的进程装配Android环境呢?最后一步就是调用ActivityThread.main()方法,而且形式很特殊,是通过抛出异常的形式,这样目的就清理调用栈,因为那些创建过程中的调用栈也没有用,只需要传递最后那些调用栈过程中得到的结果,并将结果作为参数封装成异常的形式进行抛出。是不是很巧秒啊,哈哈。
1.1 ZygoteInit.main()
ZygoteInit.java
public static void main(String argv[]) {
try {
runSelectLoop(abiList); //[1.2]
....
} catch (MethodAndArgsCaller caller) {
caller.run(); //
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
1.2 ZygoteInit.runSelectLoop()
ZygoteInit.java
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
//处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
...
}
for (int i = pollFds.length - 1; i >= 0; --i) {
//当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
// 否则进入continue,跳出本次循环。
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
//即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
// 则创建ZygoteConnection对象,并添加到fds。//[1.3]
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor()); //添加到fds.
} else {
//i>0,则代表通过socket接收来自对端的数据,并执行相应操作[2.1]
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i); //处理完则从fds中移除该文件描述符
}
}
}
}
}
我们看到这里有个大的死循环,一般死循环中肯定有阻塞时间,系统没事不可能闲着让他一直占有cpu干一写没有意义的事情,这里我们回想Process.java类中的一个方法,openZygoteSocketIfNeeded()来跟zygote进程建立链接,zygote进程收到客户端链接的请求之后执行acceptCommandPeer()因为链接并不需要数据,所以i==0,然后在创建ZygoteConnection对象,并添加到fds数组中。
我们在看看这块逻辑:
1.Process.java中通过 ZygoteState.connect(ZYGOTE_SOCKET);发起请求
2.ZygoteInit.runSelectLoop()在Os.poll(pollFds, -1);中收到请求
3. for (int i = pollFds.length - 1; i >= 0; --i) 此时i = pollFds.length - 1,由于pollFds.length=1,因为链接并不产生数据,所以不增加事件个数所以i==0
4. ZygoteConnection newPeer = acceptCommandPeer(abiList);所以创建链接并添加
5. peers.get(i).runOnce();当数据来的时候调用ZygoteConnection.runOnce()
我们不妨看看Os.poll();
的说明:
poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
The set of file descriptors to be monitored is specified in the fds
argument, which is an array of structures of the following form:
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
The caller should specify the number of items in the fds array in
nfds.
nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;
timeout:是poll函数调用阻塞的时间,单位:毫秒;
返回值:
>0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;
==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时,超时时间是timeout毫秒;
换句话说,如果所检测的socket描述符上没有任何事件发生的话,那么poll()函数会阻塞timeout所指定的毫秒时间长度之后返回,
如果timeout==0,那么poll() 函数立即返回而不阻塞
如果timeout==INFTIM,那么poll() 函数会一直阻塞下去,直到所检测的socket描述符上的感兴趣的事件发生是才返回
如果感兴趣的事件永远不发生,那么poll()就会永远阻塞下去;
poll()在等待执行IO操作。和select函数差不多,后来Linux内核升级就慢慢的用epoll代替了。
1.3 ZygoteInit.acceptCommandPeer()
ZygoteInit.java
private static ZygoteConnection acceptCommandPeer(String abiList) {
try {
return new ZygoteConnection(sServerSocket.accept(), abiList);
} catch (IOException ex) {
...
}
}
将客户端发送过来的connect()进行封装。
这里我们可能会好奇sServerSocket.accept()方法就可以得到Process.java那边的socket。怎么就是同一个了。
我们看这段证据:
我们在ZygoteInit.main()中这样执行
String socketName = "zygote";
registerZygoteSocket(socketName);
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//"ANDROID_SOCKET_";
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
这段代码就是将名称zygote设置成sServerSocket
我们再来看看Process.java那边
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//public static final String ZYGOTE_SOCKET = "zygote";
final LocalSocket zygoteSocket = new LocalSocket();//创建type为2
zygoteSocket.connect(new LocalSocketAddress(socketAddress,LocalSocketAddress.Namespace.RESERVED));
impl.connect(endpoint, 0);//将LocalSocketAddress传如connect中
osType = OsConstants.SOCK_STREAM;
fd = Os.socket(OsConstants.AF_UNIX, osType, 0);//其中fd来自与创建的type为2
connectLocal(fd, address.getName(), address.getNamespace().getId());//fd=2
private native void connectLocal(FileDescriptor fd, String name,int namespace) throws IOException;
native层此时已经知道要找的fd,name,namespace那就对应到ZygoteInit中去。
2.1 ZygoteInit.runOnce()
ZygoteInit.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//读取socket客户端发送过来的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
closeSocket();
return true;
}
PrintStream newStderr = null;
if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(new FileOutputStream(descriptors[2]));
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
//将socket客户端传递过来的参数,另封装成Arguments对象格式
parsedArgs = new Arguments(args);
...
int [] fdsToClose = { -1, -1 };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
fdsToClose[0] = fd.getInt$();
}
fd = ZygoteInit.getServerSocketFileDescriptor();
if (fd != null) {
fdsToClose[1] = fd.getInt$();
}
fd = null;
//[3.1]
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
...
}
try {
if (pid == 0) {
//子进程执行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//[2.2]
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// 不应到达此处,子进程预期的是抛出异常ZygoteInit.MethodAndArgsCaller或者执行exec().
return true;
} else {
//父进程执行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
3.1 Zygote.forkAndSpecialize()
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
VM_HOOKS.preFork(); //停止四个Deamon子线程,等待所有子线程结束之后完成gc堆的初始化
//[4.1]
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
...
//VM_HOOKS.postForkCommon的主要功能是在fork新进程后,
//启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。
VM_HOOKS.postForkCommon();
return pid;
}
4.1 com_android_internal_os_Zygote.forkAndSpecialize()
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
// 将CAP_WAKE_ALARM赋予蓝牙进程
jlong capabilities = 0;
if (uid == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
}
//4.2
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, instructionSet, appDataDir);
}
4.2 com_android_internal_os_Zygote.ForkAndSpecializeCommon()
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jstring instructionSet, jstring dataDir) {
//设置子进程的signal信号处理函数
SetSigChldHandler();
//fork子进程
pid_t pid = fork();
if (pid == 0) { //进入子进程
DetachDescriptors(env, fdsToClose); //关闭并清除文件描述符
if (!is_system_server) {
//对于非system_server子进程,则创建进程组
int rc = createProcessGroup(uid, getpid());
}
SetGids(env, javaGids); //设置设置group
SetRLimits(env, javaRlimits); //设置资源limit
int rc = setresgid(gid, gid, gid);
rc = setresuid(uid, uid, uid);
SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env); //设置调度策略
//selinux上下文
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
if (se_info_c_str == NULL && is_system_server) {
se_name_c_str = "system_server";
}
if (se_info_c_str != NULL) {
SetThreadName(se_name_c_str); //设置线程名为system_server,方便调试
}
//在Zygote子进程中,设置信号SIGCHLD的处理器恢复为默认行为
UnsetSigChldHandler();
//等价于调用zygote.callPostForkChildHooks() [3.2]
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server ? NULL : instructionSet);
...
} else if (pid > 0) {
//进入父进程,即Zygote进程
}
return pid;
}
这里必须小结一下:
- 设置新创的进程signal处理函数,这个处理函数以后会用到,只不过不是本章重点
- 进入子进程关闭文件描述
- 创建进程组
- 设置group
- 设置调度策略
也就是做一些底层的初始化工作,还有信号函数哦,别忘了
3.2 Zygote.callPostForkChildHooks()
private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
String instructionSet) {
//调用ZygoteHooks.postForkChild()
VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
}
public void postForkChild(int debugFlags, String instructionSet) {
nativePostForkChild(token, debugFlags, instructionSet);
Math.setRandomSeedInternal(System.currentTimeMillis());
}
我们这里就不看native层了,native层做的事情就是
- 设置新进程的主线程id
- 设置java堆处理线程池
- 重置gc性能数据
- 设置信号函数
这里小结下 ZygoteInit.runOnce()中调用forkAndSpecialize()方法做的事情:
- 停止Zygote的4个Daemon子线程的运行,初始化gc堆;
- 调用fork()创建新进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能。
- 启动4个Deamon子线程。
2.2 ZygoteConnection.handleChildProc()
ZygoteConnection.java
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
//关闭Zygote的socket两端的连接
closeSocket();
ZygoteInit.closeServerSocket();
if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.niceName != null) {
//设置进程名
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
//于检测进程内存泄露或溢出时
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
//执行目标类的main()方法[5.1]
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null);
}
}
5.1 RuntimeInit.zygoteInit()
RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
redirectLogStreams(); //重定向log输出
commonInit(); // 通用的一些初始化[5.2]]
nativeZygoteInit(); // zygote初始化 【见流程6.1】
applicationInit(targetSdkVersion, argv, classLoader); // 应用初始化[5.4]
}
5.2 RuntimeInit.commonInit()
private static final void commonInit() {
// 设置默认的未捕捉异常处理方法
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
// 设置市区,中国时区为"Asia/Shanghai"
TimezoneGetter.setInstance(new TimezoneGetter() {
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
//重置log配置
LogManager.getLogManager().reset();
new AndroidConfig();
// 设置默认的HTTP User-agent格式,用于 HttpURLConnection。
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
// 设置socket的tag,用于网络流量统计
NetworkManagementSocketTagger.install();
}
- 看这里看这里,这里设置了默认异常捕获的方法
- 设置了时区
- 重置了log配置
- 设置默认http
- 设置网络流量统计
6.1 AndroidRuntime.cpp
AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
gCurRuntime->onZygoteInit();
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool(); //启动新binder线程
}
这里目的是启动一个Binder线程
5.4 RuntimeInit.applicationInit()
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
//true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
nativeSetExitWithoutCleanup(true);
//设置虚拟机的内存利用率参数值为0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv); //解析参数
} catch (IllegalArgumentException ex) {
return;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//调用startClass的static方法 main() [5.5]//args.startClass为”android.app.ActivityThread”
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
5.5 RuntimeInit.invokeStaticMain()
RuntimeInit.java
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl = Class.forName(className, true, classLoader);
Method m = cl.getMethod("main", new Class[] { String[].class });
int modifiers = m.getModifiers();
...
//通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率。【见流程16】
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
我的天,终于抛出异常了,这个异常一下回到解放前:
public static void main(String argv[]) {
try {
runSelectLoop(abiList); //[1.2]
....
} catch (MethodAndArgsCaller caller) {
caller.run(); //就是这里
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
继续走起:
MethodAndArgsCaller.run()
public static class MethodAndArgsCaller extends Exception
implements Runnable {
public void run() {
try {
//根据传递过来的参数,此处反射调用ActivityThread.main()方法
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
我们不容易啊,终于通过runSelectLoop中创建的子进程抛出给ZygoteInit.java了,但是这里已经是复制过父进程的Zygote了,所以一些资源也过来了,不一样就是要初始化一些子进程的资源。我们在来回顾一下吧。
ZygoteInit.main//进入到ZygoteInit.java由于init进程导致
ZygoteInit.runSelectLoop()
ZygoteConnection.runOnce()//读取参数并调用下面方法
Zygote.forkAndSpecialize()//初始化初始化虚拟机那些工作,然后创建子进程
Zygote.nativeForkAndSpecialize()
com_android_internal_os_Zygote.ForkAndSpecializeCommon()//设置子进程signal,创建进程组,设置掉副方法等
pid = fork();
Zygote.handleChildProc()//设置进程名
RuntimeInit.zygoteInit()
commonInit();//通用的一些初始化,时区,异常处理办法
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
nativeZygoteInit();zygote初始化
onZygoteInit();
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool(); //启动新binder线程
applicationInit();应用初始化
invokeStaticMain(args.startClass, args.startArgs, classLoader);
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
mMethod.invoke(null, new Object[] { mArgs });
ActivityThread.main()//这里进行app进程里面的组件那些初始化拉起来等
看着这个调用栈,我们就从接收一个空荡荡的进程信号,创建一个空荡荡的进程,然后又一个空荡荡的进程,初始化了一下不空荡荡(gc,binder线程,异常处理,时区)的操作,让进程变得稍微丰富,此时进程具备了Android环境的能力。但是这只是app的开始,四大组件那些还没有用到不算app完全起来。
app进程启动.png
网友评论