日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android android:process=,Android app启动流程

發布時間:2025/4/5 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android android:process=,Android app启动流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

進程創建前

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 {

return startViaZygote(processClass, niceName, uid, gid, gids,

debugFlags, mountExternal, targetSdkVersion, seInfo,

abi, instructionSet, appDataDir, zygoteArgs);

} catch (ZygoteStartFailedEx ex) {

Log.e(LOG_TAG,

"Starting VM process through Zygote failed");

throw new RuntimeException(

"Starting VM process through Zygote failed", ex);

}

}

start函數里面沒有做太多的事情,直接交給了startViaZygote

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 argsForZygote = new ArrayList();

// --runtime-args, --setuid=, --setgid=,

// and --setgroups= must go first

argsForZygote.add("--runtime-args");

argsForZygote.add("--setuid=" + uid);

argsForZygote.add("--setgid=" + gid);

if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {

argsForZygote.add("--enable-jni-logging");

}

if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {

argsForZygote.add("--enable-safemode");

}

....

argsForZygote.add(processClass);

if (extraArgs != null) {

for (String arg : extraArgs) {

argsForZygote.add(arg);

}

}

return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);

}

}

startViaZygote 函數前面都是對參數的整理。

后面交給了zygoteSendArgsAndGetResult。

但是這里我們需要注意的這邊 openZygoteSocketIfNeeded 會打開一個socket,用于和zygote通訊,這個zygote之所以要一個abi參數因為在64位系統中有兩個zygote進程。

root 264 1 1173156 127704 0 0000000000 S zygote64

root 265 1 934112 114496 0 0000000000 S zygote

就分別通訊的意思。

private static ProcessStartResult zygoteSendArgsAndGetResult(

ZygoteState zygoteState, ArrayList args)

throws ZygoteStartFailedEx {

try {

int sz = args.size();

for (int i = 0; i < sz; i++) {

if (args.get(i).indexOf('\n') >= 0) {

throw new ZygoteStartFailedEx("embedded newlines not allowed");

}

}

final BufferedWriter writer = zygoteState.writer;

final DataInputStream inputStream = zygoteState.inputStream;

writer.write(Integer.toString(args.size()));

writer.newLine();

for (int i = 0; i < sz; i++) {

String arg = args.get(i);

writer.write(arg);

writer.newLine();

}

writer.flush();

ProcessStartResult result = new ProcessStartResult();

result.pid = inputStream.readInt();

result.usingWrapper = inputStream.readBoolean();

if (result.pid < 0) {

throw new ZygoteStartFailedEx("fork() failed");

}

return result;

} catch (IOException ex) {

zygoteState.close();

throw new ZygoteStartFailedEx(ex);

}

}

上一步拿到了zygoteState 現在進行通訊,首先進行的參數的校驗,如果沒有問題就通過一個一個參數write傳輸過去給zygote。

zygote拿到這些參數就會給你創建好需要的進程。

然后返回結果通過read讀取出來。

那么zygote那邊是怎么創建進程呢?我們來看下zygote那邊的工作。

進程的創建

zygote循環

zygoteInit.main()函數是zygote啟動的時候會執行的函數,關于zygote啟動這里不在詳細解析。

public static void main(String argv[]) {

try {

runSelectLoop(abiList);

} catch (MethodAndArgsCaller caller) {

caller.run();

} catch (RuntimeException ex) {

closeServerSocket();

throw ex;

}

}

在main函數中會調用。runSelectLoop開啟socket等待。

我們這里留意下這MethodAndArgsCaller異常。

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {

ArrayList fds = new ArrayList();

ArrayList peers = new ArrayList();

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 {

Os.poll(pollFds, -1);

} catch (ErrnoException ex) {

throw new RuntimeException("poll failed", ex);

}

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

if ((pollFds[i].revents & POLLIN) == 0) {

continue;

}

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);

}

}

}

}

}

zygote起來以后會一直在這邊循環等待,等待你們連接我并把需要創建進程的參數傳輸給我。有連接過來了,就會執行runOnce函數。

runOnce

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

String args[];

Arguments parsedArgs = null;

FileDescriptor[] descriptors;

try {

args = readArgumentList();

descriptors = mSocket.getAncillaryFileDescriptors();

} catch (IOException ex) {

Log.w(TAG, "IOException on command socket " + ex.getMessage());

closeSocket();

return true;

}

try {

parsedArgs = new Arguments(args);

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) {

logAndPrintError(newStderr, "Exception creating pipe", ex);

} catch (IllegalArgumentException ex) {

logAndPrintError(newStderr, "Invalid zygote arguments", ex);

} catch (ZygoteSecurityException ex) {

logAndPrintError(newStderr,

"Zygote security policy prevents request: ", ex);

}

try {

if (pid == 0) {

handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

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

// throw ZygoteInit.MethodAndArgsCaller or exec().

return true;

} else {

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

}

} finally {

IoUtils.closeQuietly(childPipeFd);

IoUtils.closeQuietly(serverPipeFd);

}

}

這里關鍵的地方就是forkAndSpecialize 前面都是收集參數等待。

后forkAndSpecialize fork進程后,父進程和紫禁城分道揚鑣。----這個是linux進程創建的知識了

接下來我們要分開兩條不同關注點去看進程的創建了

---? forkAndSpecialize 會調用linux的fork系統調用創建進程,創建后我們關注它的一些環境的建立。

---handleChildProc 進程創建后回去加載app的入口也就是ActivityThread。我們關注它是怎去加載的。

如果是單單看應用的啟動,往應用層去理解呢,其實不太需要知道fork流程,如果想更深入了解系統的運行機制,可以一起來看下forkAndSpecialize到底做來什么東西。

進程的fork

上面講到forkAndSpecialize 函數,我們這節的目的,看下forkAndSpecialize是怎么到底層調用linux的fork系統調用,從而開辟一個進程的。

要了解fork系統調用和運用的需要去了解linux的應用開發。這樣才比較好了解進程的啟動,在linux里面為什么用一個fork就創建了一個進程。

這個是需要一個基礎知識的。

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) {

...

int pid = nativeForkAndSpecialize(

uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,

instructionSet, appDataDir);

...

return pid;

}

native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,

int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,

String instructionSet, String appDataDir);

我們來看到forkAndSpecialize 什么都沒有做直接交給了nativeForkAndSpecialize,而nativeForkAndSpecialize是一個jni底層的函數。

這個函數的實現在com_android_internal_os_Zygote.cpp (frameworks\base\core\jni)

static const JNINativeMethod gMethods[] = {

{ "nativeForkAndSpecialize",

"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",

(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },

在這個com_android_internal_os_Zygote.cpp 文件里面,我們看到它的jni實現是com_android_internal_os_Zygote_nativeForkAndSpecialize

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) {

jlong capabilities = 0;

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_nativeForkAndSpecialize 這個函數也沒有做太多的事情,直接交給了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) {

SetSigChldHandler();

...

pid_t pid = fork();

if (pid == 0) {

..

if (!is_system_server) {

int rc = createProcessGroup(uid, getpid());

if (rc != 0) {

if (rc == -EROFS) {

ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");

} else {

ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));

}

}

}

SetGids(env, javaGids);

...

int rc = setresgid(gid, gid, gid);

...

SetCapabilities(env, permittedCapabilities, effectiveCapabilities);

SetSchedulerPolicy(env);

...

rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);

...

if (se_info_c_str != NULL) {

SetThreadName(se_name_c_str);

}

...

} else if (pid > 0) {

...

}

return pid;

}

這個函數做的事情就有點多了,關鍵的是我們看到了fork()函數。

---在這個fork()函數之前做的是一些signal的設置

---fork()完成了以后兵分兩路,子進程會去做很多gid 、scheduler 和 selinux等等的設置。

到這里我們就完整的看到了一個進程創建的過程。返回pid。

handleChildProc

現在進程出來了,我們需要一路返回,看看我們的進程會去做那些工作,是怎么走入到我們的apk代碼里面的,主要是走到ActivityThread的過程。

我們回到handleChildProc,里面來。

private void handleChildProc(Arguments parsedArgs,

FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)

throws ZygoteInit.MethodAndArgsCaller {

if (parsedArgs.invokeWith != null) {

WrapperInit.execApplication(parsedArgs.invokeWith,

parsedArgs.niceName, parsedArgs.targetSdkVersion,

VMRuntime.getCurrentInstructionSet(),

pipeFd, parsedArgs.remainingArgs);

} else {

RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,

parsedArgs.remainingArgs, null /* classLoader */);

}

}

}

我們的進程已經創建完成來。handleChildProc是首先會調用的函數,而這個函數又調用來RuntimeInit.zygoteInit,為什么是講這個函數而不去講上面的函數?

我這里講一個簡單的linux知識。

linux進程創建也是一樣的會直接fork,fork完成后如果你要加載代碼一般是用execv系統調用去加載代碼的,但是Android,使用的是java虛擬機。

所以,上面的流程是給一些本地進程走的。而java是通過Class進行類加載,來我們來一口氣讀完下面三個函數。

看下是怎么類加載的。

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)

throws ZygoteInit.MethodAndArgsCaller {

...

applicationInit(targetSdkVersion, argv, classLoader);

}

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)

throws ZygoteInit.MethodAndArgsCaller {

...

VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);

VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

...

invokeStaticMain(args.startClass, args.startArgs, classLoader);

}

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)

throws ZygoteInit.MethodAndArgsCaller {

Class> cl;

try {

cl = Class.forName(className, true, classLoader);

} catch (ClassNotFoundException ex) {

...

}

Method m;

try {

m = cl.getMethod("main", new Class[] { String[].class });

} catch (NoSuchMethodException ex) {

...

}

...

throw new ZygoteInit.MethodAndArgsCaller(m, argv);

}

這里我們關注下面流程:

1. 首先設置虛擬機的環境

2. 調用invokeStaticMain

3.在invokeStaticMain,我們找到這個類也就是ActivityThread類,這到這個類的Method,也就是main函數。

4.最后居然沒有運行這個類而是拋出一個異常。很匪夷所思,根據反射調用的話,應該是要 m.invoke(null, arg);才對的。

那么它拋出這個異常是在哪里catch的呢?

還記得文章最前面我們說要關注的拋出的異常嗎?

在前面zygote循環的時候我說要關注的異常。

public static void main(String argv[]) {

try {

runSelectLoop(abiList);

} catch (MethodAndArgsCaller caller) {

caller.run();

} catch (RuntimeException ex) {

closeServerSocket();

throw ex;

}

}

他就是在這里catch了這個異常然后調用了這個異常的run函數。

public MethodAndArgsCaller(Method method, String[] args) {

mMethod = method;

mArgs = args;

}

public void run() {

try {

mMethod.invoke(null, new Object[] { mArgs });

} catch (IllegalAccessException ex) {

throw new RuntimeException(ex);

} catch (InvocationTargetException ex) {

...

throw new RuntimeException(ex);

}

}

然后再這里進行了invoke反射調用。

至于為什么要通過拋出異常的方法去做這個調用而不是直接調用,網上早有人給出了答案。這里就不多說。

到現在整個進程啟動的流程就結束了。

ActivityThread類加載起來以后,會和ams交互,接下來會調用到你的activity的onCreate方法,onResume方法。

然后你的apk就完美運行了。

總結

以上是生活随笔為你收集整理的android android:process=,Android app启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 女人下面流白浆的视频 | 日韩精品一区二区三区不卡在线 | 超碰人人澡 | 91精品人妻一区二区三区果冻 | 交专区videossex另类 | 国产成人精品视频ⅴa片软件竹菊 | 日本一区二区三区在线播放 | 日本人妻换人妻毛片 | 开心激情站 | 在线播放色 | 你懂的视频在线播放 | 国产精品一 | 少妇被躁爽到高潮 | 色婷婷久久五月综合成人 | 国产精品23p| 伊伊综合网 | 精品一区二区av | 天堂一区 | 美女无遮挡免费网站 | 免费成人电影在线观看 | 91干视频| 日本五十路女优 | 老鸭窝av在线| 色噜噜在线观看 | 国产盗摄精品一区二区酒店 | 草草影院最新网址 | 欧美性白人极品1819hd | 最近中文字幕在线观看 | 一级特黄aa大片欧美 | 国产在线自| 国产免费观看久久黄av片 | 污视频免费网站 | 91久久精品www人人做人人爽 | 禁断介护av一区二区 | 麻豆乱码国产一区二区三区 | 国产女人18毛片18精品 | 亚洲精品福利在线观看 | 女人高潮被爽到呻吟在线观看 | 求欧美精品网址 | 久久精品国产欧美亚洲人人爽 | 快播视频在线观看 | 在线免费观看成人 | 精品看片| 99热在线这里只有精品 | 欧美老女人性生活视频 | 91麻豆精品国产91久久久久久久久 | 久久夜色精品国产欧美乱极品 | 国产极品一区 | 中文字幕亚洲一区 | 国产精品无圣光 | 91快射 | 一区二区三区免费高清视频 | 粉豆av | 亚洲成人网在线播放 | 日本国产一区 | 90岁肥老奶奶毛毛外套 | 久久久久久久久久久久久久久 | 国产第二页 | 毛片9| 亚洲色图13p | av色图片| 国内精久久久久久久久久人 | 亚洲国产精品久久人人爱 | 性猛交富婆╳xxx乱大交麻豆 | 国产精品一级二级 | 欧美不卡视频在线观看 | 国产免费黄色av | 波多野结衣视频一区 | 在线视频久 | 伊人久久香 | 我把护士日出水了视频90分钟 | 精品人妻久久久久久888不卡 | 好吊操视频这里只有精品 | 国产第一页av | 淫僧荡尼巨乳(h)小说 | 黑人巨大av | 粗暴video蹂躏hd | 一区视频| 久久人人爽人人 | 粉嫩av网 | 一区二区三区国产在线观看 | 各种含道具高h调教1v1男男 | 日本黄网站 | 国产清纯白嫩初高中在线观看性色 | 欧美日韩一区二区三区不卡 | 成人手机在线观看 | 美女赤身免费网站 | 在线免费观看黄色av | 操综合 | 亚洲精品美女在线观看 | 一区二区三区在线视频免费观看 | 亚洲免费网站在线观看 | www亚洲视频 | 成年激情网 | 日韩精品无码一区二区三区久久久 | 国产成人综合久久 | 相亲对象是问题学生动漫免费观看 | 夜夜骑夜夜操 | 国产欧美一区二区精品性色超碰 |