/frameworks/base/core/java/com/android/internal/os/ - ZygoteInit.java - ZygoteConnection.java - RuntimeInit.java - Zygote.java /frameworks/base/core/java/android/os/Process.java /frameworks/base/core/jni/com_android_internal_os_Zygote.cpp /frameworks/base/core/jni/AndroidRuntime.cpp /frameworks/base/cmds/app_process/App_main.cpp (內含AppRuntime類) /libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java /art/runtime/native/dalvik_system_ZygoteHooks.cc /art/runtime/Runtime.cc /art/runtime/Thread.cc /art/runtime/signal_catcher.cc
本文要介紹的是進程的建立,先簡單說說進程與線程的區別。php
進程:每一個App
在啓動前必須先建立一個進程,該進程是由Zygote
fork出來的,進程具備獨立的資源空間,用於承載App上運行的各類Activity/Service等組件。進程對於上層應用來講是徹底透明的,這也是google有意爲之,讓App程序都是運行在Android Runtime。大多數狀況一個App
就運行在一個進程中,除非在AndroidManifest.xml中配置Android:process
屬性,或經過native代碼fork進程。css
線程:線程對應用開發者來講很是熟悉,好比每次new Thread().start()
都會建立一個新的線程,該線程並無本身獨立的地址空間,而是與其所在進程之間資源共享。從Linux角度來講進程與線程都是一個task_struct結構體,除了是否共享資源外,並無其餘本質的區別。java
在接下來的文章,會涉及到system_server進程和Zygote進程,下面簡要這兩個進程:linux
system_server
進程:是用於管理整個Java framework層,包含ActivityManager,PowerManager等各類系統服務;Zygote
進程:是Android系統的首個Java進程,Zygote是全部Java進程的父進程,包括 system_server
進程以及全部的App進程都是Zygote的子進程,注意這裏說的是子進程,而非子線程。若是想更進一步瞭解system_server進程和Zygote進程在整個Android系統所處的地位,可查看個人另外一個文章Android系統-開篇。android
對於大多數的應用開發者來講建立線程比較熟悉,而對於建立進程並無太多的概念。對於系統工程師或者高級開發者,仍是有很必要了解Android系統是如何一步步地建立出一個進程的。先來看一張進程建立過程的簡要圖:git
圖解:數組
ZygoteInit.main()
後便進入runSelectLoop()
循環體內,當有客戶端鏈接時便會執行ZygoteConnection.runOnce()方法,再通過層層調用後fork出新的應用進程;接下來,依次從system_server進程發起請求
到Zygote建立進程
,再到新進程的運行
這3大塊展開講解進程建立是一個怎樣的過程。安全
[-> 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 { //【見小節2】 return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, zygoteArgs); } catch (ZygoteStartFailedEx ex) { throw new RuntimeException(""); } }
[-> Process.java]app
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); } } //【見小節3】 return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }
該過程主要工做是生成argsForZygote
數組,該數組保存了進程的uid、gid、groups、target-sdk、nice-name等一系列的參數。
[-> Process.java]
private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { //其中zygoteState 【見小節3.1】 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; //對於等待時長問題,Google正在考慮此處是否應該有一個timeout,但目前是沒有的。 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進程發送一個參數列表,而後進入阻塞等待狀態,直到遠端的socket服務端發送回來新建立的進程pid才返回。
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; } ... }
openZygoteSocketIfNeeded(abi)
方法是根據當前的abi來選擇與zygote仍是zygote64來進行通訊。
既然system_server進程的zygoteSendArgsAndGetResult()方法經過socket向Zygote進程發送消息,這是便會喚醒Zygote進程,來響應socket客戶端的請求(即system_server端),接下來的操做即是在Zygote來建立進程【見小節4】
文章Android系統啓動-zygote篇已介紹,簡單來講就是Zygote進程是由由init進程而建立的,進程啓動以後調用ZygoteInit.main()方法,通過建立socket管道,預加載資源後,便進程runSelectLoop()方法。
[–>ZygoteInit.java]
public static void main(String argv[]) { try { runSelectLoop(abiList); //【見小節5】 .... } catch (MethodAndArgsCaller caller) { caller.run(); //【見小節16】 } catch (RuntimeException ex) { closeServerSocket(); throw ex; } }
後續會講到runSelectLoop()方法會拋出異常MethodAndArgsCaller
,從而進入caller.run()方法。
[-> 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) { //採用I/O多路複用機制,當接收到客戶端發出鏈接請求 或者數據處理請求到來,則往下執行; // 不然進入continue,跳出本次循環。 if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { //即fds[0],表明的是sServerSocket,則意味着有客戶端鏈接請求; // 則建立ZygoteConnection對象,並添加到fds。//【見小節5.1】 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); //添加到fds. } else { //i>0,則表明經過socket接收來自對端的數據,並執行相應操做【見小節6】 boolean done = peers.get(i).runOnce(); if (done) { peers.remove(i); fds.remove(i); //處理完則從fds中移除該文件描述符 } } } } }
該方法主要功能:
[-> ZygoteInit.java]
private static ZygoteConnection acceptCommandPeer(String abiList) { try { return new ZygoteConnection(sServerSocket.accept(), abiList); } catch (IOException ex) { ... } }
接收客戶端發送過來的connect()操做,Zygote做爲服務端執行accept()操做。 再後面客戶端調用write()寫數據,Zygote進程調用read()讀數據。
沒有鏈接請求時會進入休眠狀態,當有建立新進程的鏈接請求時,喚醒Zygote進程,建立Socket通道ZygoteConnection,而後執行ZygoteConnection的runOnce()方法。
[-> ZygoteConnection.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 { //將binder客戶端傳遞過來的參數,解析成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; //【見小節7】 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; //【見小節13】 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); } }
[-> Zygote.java]
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(); //【見小節8】 int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir); //【見小節9】 ... VM_HOOKS.postForkCommon(); //【見小節11】 return pid; }
VM_HOOKS是Zygote對象的靜態成員變量:VM_HOOKS = new ZygoteHooks();
先說說Zygote進程,以下圖:
從圖中可知Zygote進程有4個Daemon子線程分別是ReferenceQueueDaemon,FinalizerDaemon,FinalizerWatchdogDaemon,HeapTaskDaemon。圖中線程名顯示的並不完整是因爲底層的進程結構體task_struct
是由長度爲16的char型數組保存,超過15個字符便會截斷。
可能有人會問zygote64進程不是還有system_server,com.android.phone等子線程,怎麼會只有4個呢?那是由於這些並非Zygote子線程,而是Zygote的子進程。在圖中用紅色圈起來的是進程的VSIZE,virtual size),表明的是進程虛擬地址空間大小。線程與進程的最爲本質的區別即是是否共享內存空間,圖中VSIZE和Zygote進程相同的纔是Zygote的子線程,不然就是Zygote的子進程。
[-> ZygoteHooks.java]
public void preFork() { Daemons.stop(); //中止4個Daemon子線程【見小節8.1】 waitUntilAllThreadsStopped(); //等待全部子線程結束【見小節8.2】 token = nativePreFork(); //完成gc堆的初始化工做【見小節8.3】 }
public static void stop() { HeapTaskDaemon.INSTANCE.stop(); //Java堆整理線程 ReferenceQueueDaemon.INSTANCE.stop(); //引用隊列線程 FinalizerDaemon.INSTANCE.stop(); //析構線程 FinalizerWatchdogDaemon.INSTANCE.stop(); //析構監控線程 }
此處守護線程Stop方式是先調用目標線程interrrupt()方法,而後再調用目標線程join()方法,等待線程執行完成。
private static void waitUntilAllThreadsStopped() { File tasks = new File("/proc/self/task"); // 當/proc中線程數大於1,就出讓CPU直到只有一個線程,才退出循環 while (tasks.list().length > 1) { Thread.yield(); } }
nativePreFork經過JNI最終調用以下方法:
[-> dalvik_system_ZygoteHooks.cc]
static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) { Runtime* runtime = Runtime::Current(); runtime->PreZygoteFork(); // 見下文 if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) { Trace::Pause(); } //將線程轉換爲long型並保存到token,該過程是非安全的 return reinterpret_cast<jlong>(ThreadForEnv(env)); }
至於runtime->PreZygoteFork的過程:
void Runtime::PreZygoteFork() {
// 堆的初始化工做。這裏就不繼續再往下追art虛擬機 heap_->PreZygoteFork(); }
VM_HOOKS.preFork()的主要功能即是中止Zygote的4個Daemon子線程的運行,等待並確保Zygote是單線程(用於提高fork效率),並等待這些線程的中止,初始化gc堆的工做, 並將線程轉換爲long型並保存到token
nativeForkAndSpecialize()經過JNI最終調用調用以下方法:
[-> com_android_internal_os_Zygote.cpp]
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); } //【見流程10】 return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, instructionSet, appDataDir); }
[-> com_android_internal_os_Zygote.cpp]
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子進程 【見流程10.1】 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() 【見流程10.2】 env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags, is_system_server ? NULL : instructionSet); ... } else if (pid > 0) { //進入父進程,即Zygote進程 } return pid; }
fork()採用copy on write技術,這是linux建立進程的標準方法,調用一次,返回兩次,返回值有3種類型。
fork()的主要工做是尋找空閒的進程號pid,而後從父進程拷貝進程信息,例如數據段和代碼段,fork()後子進程要執行的代碼等。 Zygote進程是全部Android進程的母體,包括system_server和各個App進程。zygote利用fork()方法生成新進程,對於新進程A複用Zygote進程自己的資源,再加上新進程A相關的資源,構成新的應用進程A。其中下圖中Zygote進程的libc、vm、preloaded classes、preloaded resources是如何生成的,可查看另外一個文章Android系統啓動-zygote篇,見下圖:
copy-on-write過程:當父子進程任一方修改內存數據時(這是on-write時機),才發生缺頁中斷,從而分配新的物理內存(這是copy操做)。
copy-on-write原理:寫時拷貝是指子進程與父進程的頁表都所指向同一個塊物理內存,fork過程只拷貝父進程的頁表,並標記這些頁表是隻讀的。父子進程共用同一份物理內存,若是父子進程任一方想要修改這塊物理內存,那麼會觸發缺頁異常(page fault),Linux收到該中斷便會建立新的物理內存,並將兩個物理內存標記設置爲可寫狀態,從而父子進程都有各自獨立的物理內存。
[-> Zygote.java]
private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer, String instructionSet) { //調用ZygoteHooks.postForkChild() VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet); }
[-> ZygoteHooks.java]
public void postForkChild(int debugFlags, String instructionSet) { //【見流程10.3】 nativePostForkChild(token, debugFlags, instructionSet); Math.setRandomSeedInternal(System.currentTimeMillis()); }
在這裏,設置了新進程Random隨機數種子爲當前系統時間,也就是在進程建立的那一刻就決定了將來隨機數的狀況,也就是僞隨機。
nativePostForkChild經過JNI最終調用調用以下方法:
[-> dalvik_system_ZygoteHooks.cc]
static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags, jstring instruction_set) { //此處token是由[小節8.3]建立的,記錄着當前線程 Thread* thread = reinterpret_cast<Thread*>(token); //設置新進程的主線程id thread->InitAfterFork(); .. if (instruction_set != nullptr) { ScopedUtfChars isa_string(env, instruction_set); InstructionSet isa = GetInstructionSetFromString(isa_string.c_str()); Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload; if (isa != kNone && isa != kRuntimeISA) { action = Runtime::NativeBridgeAction::kInitialize; } //【見流程10.4】 Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str()); } else { Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr); } }
[-> Runtime.cc]
void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) { is_zygote_ = false; if (is_native_bridge_loaded_) { switch (action) { case NativeBridgeAction::kUnload: UnloadNativeBridge(); //卸載用於跨平臺的橋連庫 is_native_bridge_loaded_ = false; break; case NativeBridgeAction::kInitialize: InitializeNativeBridge(env, isa);//初始化用於跨平臺的橋連庫 break; } } //建立Java堆處理的線程池 heap_->CreateThreadPool(); //重置gc性能數據,以保證進程在建立以前的GCs不會計算到當前app上。 heap_->ResetGcPerformanceInfo(); if (jit_.get() == nullptr && jit_options_->UseJIT()) { //當flag被設置,而且尚未建立JIT時,則建立JIT CreateJit(); } //設置信號處理函數 StartSignalCatcher(); //啓動JDWP線程,當命令debuger的flags指定"suspend=y"時,則暫停runtime Dbg::StartJdwp(); }
關於信號處理過程,其代碼位於signal_catcher.cc文件中,後續會單獨講解。
[-> ZygoteHooks.java]
public void postForkCommon() { Daemons.start(); } public static void start() { ReferenceQueueDaemon.INSTANCE.start(); FinalizerDaemon.INSTANCE.start(); FinalizerWatchdogDaemon.INSTANCE.start(); HeapTaskDaemon.INSTANCE.start(); }
VM_HOOKS.postForkCommon的主要功能是在fork新進程後,啓動Zygote的4個Daemon線程,java堆整理,引用隊列,以及析構線程。
該方法主要功能:
fork()
建立新進程,設置新進程的主線程id,重置gc性能數據,設置信號處理函數等功能。其調用關係鏈:
Zygote.forkAndSpecialize ZygoteHooks.preFork Daemons.stop ZygoteHooks.nativePreFork dalvik_system_ZygoteHooks.ZygoteHooks_nativePreFork Runtime::PreZygoteFork heap_->PreZygoteFork() Zygote.nativeForkAndSpecialize com_android_internal_os_Zygote.ForkAndSpecializeCommon fork() Zygote.callPostForkChildHooks ZygoteHooks.postForkChild dalvik_system_ZygoteHooks.nativePostForkChild Runtime::DidForkFromZygote ZygoteHooks.postForkCommon Daemons.start
時序圖: 點擊查看大圖
到此App進程已完成了建立的全部工做,接下來開始新建立的App進程的工做。在前面ZygoteConnection.runOnce方法中,zygote進程執行完forkAndSpecialize()
後,新建立的App進程便進入handleChildProc()
方法,下面的操做運行在App進程。
在前面[流程6]runOnce()過程當中調用forkAndSpecialize()建立完新進程後,返回值pid=0(即運行在子進程)繼續開始執行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()方法 【見流程14】 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null); } }
[–>RuntimeInit.java]
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { redirectLogStreams(); //重定向log輸出 commonInit(); // 通用的一些初始化【見流程14.1】 nativeZygoteInit(); // zygote初始化 【見流程14.2】 applicationInit(targetSdkVersion, argv, classLoader); // 應用初始化【見流程14.3】 }
[–>RuntimeInit.java]
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(); }
默認的HTTP User-agent格式,例如:
"Dalvik/1.1.0 (Linux; U; Android 6.0.1;LenovoX3c70 Build/LMY47V)".
nativeZygoteInit()所對應的jni方法以下:
[–>AndroidRuntime.cpp]
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { //此處的gCurRuntime爲AppRuntime,是在AndroidRuntime.cpp中定義的 gCurRuntime->onZygoteInit(); }
[–>app_main.cpp]
virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); proc->startThreadPool(); //啓動新binder線程 }
[–>RuntimeInit.java]
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() 【見流程15】 invokeStaticMain(args.startClass, args.startArgs, classLoader); }
此處args.startClass爲」android.app.ActivityThread」。
[–>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); }
invokeStaticMain()方法中拋出的異常MethodAndArgsCaller
caller,該方法的參數m
是指main()方法, argv
是指ActivityThread. 根據前面的【流程4】中可知,下一步進入caller.run()方法,也就是MethodAndArgsCaller.run()。
[–>ZygoteInit.java]
public static class MethodAndArgsCaller extends Exception implements Runnable { public void run() { try { //根據傳遞過來的參數,此處反射調用ActivityThread.main()方法【見流程17】 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); } } }
到此,總算是進入到了ActivityThread類的main()方法。
[–> ActivityThread.java]
public static void main(String[] args) { ... Environment.initForCurrentUser(); ... Process.setArgV0("<pre-initialized>"); //建立主線程looper Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); //attach到系統進程 thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } //主線程進入循環狀態 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
Process.start()方法是阻塞操做,等待直到進程建立完成並返回相應的新進程pid,才完成該方法。
當App第一次啓動時或者啓動遠程Service,即AndroidManifest.xml文件中定義了process:remote屬性時,都須要建立進程。好比當用戶點擊桌面的某個App圖標,桌面自己是一個app(即Launcher App),那麼Launcher所在進程即是此次建立新進程的發起進程,該經過binder發送消息給system_server進程,該進程承載着整個java framework的核心服務。system_server進程從Process.start開始,執行建立進程,流程圖(以進程的視角)以下:
點擊查看大圖
上圖中,system_server
進程經過socket IPC通道向zygote
進程通訊,zygote
在fork出新進程後因爲fork調用一次,返回兩次,即在zygote進程中調用一次,在zygote進程和子進程中各返回一次,從而能進入子進程來執行代碼。該調用流程圖的過程:
即流程1~3
):經過Process.start()方法發起建立新進程請求,會先收集各類新進程uid、gid、nice-name等相關的參數,而後經過socket通道發送給zygote進程;即流程4~12
):接收到system_server進程發送過來的參數後封裝成Arguments對象,圖中綠色框forkAndSpecialize()方法是進程建立過程當中最爲核心的一個環節(詳見流程6),其具體工做是依次執行下面的3個方法:
即流程13~15
):進入handleChildProc()方法,設置進程名,打開binder驅動,啓動新的binder線程;而後設置art虛擬機參數,再反射調用目標類的main()方法,即Activity.main()方法。再以後的流程,若是是startActivity則將要進入Activity的onCreate/onStart/onResume等生命週期;若是是startService則將要進入Service的onCreate等生命週期。
Tips: [小節11]RuntimeInit.java的方法nativeZygoteInit()會調用到onZygoteInit(),這個過程當中有startThreadPool()建立Binder線程池。也就是說每一個進程不管是否包含任何activity等組件,必定至少會包含一個Binder線程。