版權(quán)說明:本文為 開開向前沖 原創(chuàng)文章全肮,轉(zhuǎn)載請注明出處;
注:限于作者水平有限寄症,文中有不對的地方還請指教
我剛開始接觸Android 是作為一名APP開發(fā)者示姿,因此在剛開始看到 Zygote 時缩歪,并不明白它是什么,
現(xiàn)在我在這里記錄一下自己對于 Zygote 的理解涕烧;
Zygote —— 進程起源地
1.Zygote 啟動:init.zygote32.rc
/system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
/system/bin/app_process是Zygote進程的可執(zhí)行程序杏瞻,后續(xù)都是啟動參數(shù)衙荐;
app_process的源碼路徑:
/frameworks/base/cmds/app_process/app_main.cpp
1-1. main方法
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {//Selinux相關(guān)捞挥,防止動態(tài)更改權(quán)限
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) { //老版本內(nèi)核一直返回EINVAL
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0] //忽略第一個參數(shù)
argc--; //參數(shù)個數(shù)減一
argv++; //指向argv[1]
// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
對于init.zygote32.rc中service Zygote 的參數(shù)已經(jīng)在main方法的注釋中都有講解;
" -Xzygote"是VM參數(shù)忧吟;
"/system/bin"是可執(zhí)行程序app_process的父目錄树肃,可以不關(guān)注;
"--zygote" : Start in zygote mode
"--start-system-server" : Start the system server.
"--application" : Start in application (stand alone, non zygote) mode.
"--nice-name" : The nice name for this process.
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
第一個參數(shù)從"/system/bin/app_process"算起瀑罗,argc = 5(參數(shù)長度),argv = argv[0] = "/system/bin/app_process"
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--; //參數(shù)個數(shù)減一
argv++; //指向argv[1]
上述代碼執(zhí)行完成后雏掠,
argc = 4 argv指向參數(shù)原始參數(shù)的argv[1]斩祭,即argv = "-Xzygote"
上面忽略第一個參數(shù)的原因相比你已經(jīng)了解——當實參傳給main函數(shù)之后,argv的第一個元素指向程序的名字或者一個空字符串乡话,接下來的元素依次傳遞給命令行提供的實參摧玫,最后一個指針之后的元素保證為0。
接下來是一個循環(huán)
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') { //argv[i]是一個字符串數(shù)組绑青,所以此時是判斷參數(shù)頭部是否帶有"-"
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));//這個循環(huán)的核心就是執(zhí)行這段代碼诬像,從判斷條件中知道
//只有 "-Xzygote"符合要求,即給虛擬機設(shè)置參數(shù)
}
上述代碼循環(huán)是在判斷第二個參數(shù)時退出的闸婴,循環(huán)退出時i = 1坏挠,argc = 4
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument. //此時i = 2
while (i < argc) { //argc = 4
const char* arg = argv[i++]; //從argv[2]開始算起,即跳過了/system/bin
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
上述這段代碼很簡單邪乍,就是根據(jù)傳遞的argv參數(shù)來設(shè)置幾個變量降狠,后續(xù)肯定會根據(jù)這個幾個變量來執(zhí)行相關(guān)操作;一共循環(huán)兩次庇楞,上述代碼執(zhí)行完成后i = 4榜配,但是argv的指向-Xzygote;循環(huán)結(jié)束后吕晌,變量的值如下:
zygote = true;
niceName = ZYGOTE_NICE_NAME;
startSystemServer = true;
循環(huán)結(jié)束后會根據(jù)上述賦值的變量來進行一些初始化操作蛋褥,代碼如下:
Vector<String8> args; //該變量后續(xù)會作為AppRuntime 的啟動參數(shù)傳遞
if (!className.isEmpty()) { //className 在上述代碼中沒有賦值,所以className 為空
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else { //className 為空睛驳,走該流程==================>>
// We're in zygote mode.
maybeCreateDalvikCache(); //創(chuàng)建虛擬機Cache 文件烙心,目錄在/data/dalvik-cache/下膜廊,
// 我的機器是arm架構(gòu),所以在這個目錄下生成一個arm的文件夾弃理,里面存放的都是一些dex文件溃论;
if (startSystemServer) {
args.add(String8("start-system-server"));//添加start-system-server參數(shù)
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
1-2. maybeCreateDalvikCache() 方法
static void maybeCreateDalvikCache() {
#if defined(__aarch64__)
static const char kInstructionSet[] = "arm64";
#elif defined(__x86_64__)
static const char kInstructionSet[] = "x86_64";
#elif defined(__arm__)
static const char kInstructionSet[] = "arm";
#elif defined(__i386__)
static const char kInstructionSet[] = "x86";
#elif defined (__mips__)
static const char kInstructionSet[] = "mips";
#else
#error "Unknown instruction set"
#endif
const char* androidRoot = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset");
char dalvikCacheDir[PATH_MAX];
const int numChars = snprintf(dalvikCacheDir, PATH_MAX,
"%s/dalvik-cache/%s", androidRoot, kInstructionSet);//dalvikCacheDir最終為/data/dalvik-cache/arm
LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
"Error constructing dalvik cache : %s", strerror(errno));
int result = mkdir(dalvikCacheDir, 0711);
LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST),
"Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno));
// We always perform these steps because the directory might
// already exist, with wider permissions and a different owner
// than we'd like.
result = chown(dalvikCacheDir, AID_ROOT, AID_ROOT);//修改用戶和用戶主組為ROOT
LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));
result = chmod(dalvikCacheDir, 0711);
LOG_ALWAYS_FATAL_IF((result < 0),
"Error changing dalvik-cache permissions : %s", strerror(errno));
}
maybeCreateDalvikCache 完成的功能如下:
1. 設(shè)置虛擬機指令集;
2. 創(chuàng)建虛擬機緩存目錄痘昌;目錄為/data/dalvik-cache/arm钥勋,后面的arm是根據(jù)簽名機器指令集賦值的;我的機器為arm辆苔;
3. 修改目錄的USER和GROUP 為ROOT 用戶算灸;
4. 修改目錄權(quán)限為"0711"(-rwx--x--x),即目錄擁有者有讀寫執(zhí)行權(quán)限驻啤,其他用戶只有執(zhí)行權(quán)限菲驴;
maybeCreateDalvikCache 后:
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { //根據(jù)ABI_LIST_PROPERTY屬性獲取abi-list參數(shù)
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);// 添加abi-list參數(shù)
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) { //開機執(zhí)行這句代碼前i = 4,argc = 4,所以下面程序不會執(zhí)行骑冗,
//即沒有參數(shù)需要添加了赊瞬,如果還有參數(shù)會接著添加
args.add(String8(argv[i]));//將參數(shù)添加到args,再傳給Runtime
}
......
......
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);//啟動ZygoteInit贼涩,接收上面?zhèn)鬟f過來的參數(shù)args巧涧,
//即從init.rc傳遞過來的參數(shù);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);//調(diào)用AndroidRuntime的start方法
//啟動RuntimeInit
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
注:這里所說的過程是第一次開機Zygote 的處理過程遥倦,參數(shù)也是開機過程從init.rc中傳遞的參數(shù)谤绳,我嘗試使用adb install 安裝應(yīng)用,也會調(diào)用Zygote袒哥,但是參數(shù)和上述描述不一樣缩筛;
到此app_main的main方法執(zhí)行結(jié)束,程序?qū)⒗^續(xù)執(zhí)行AndroidRuntime的start方法堡称;
2. AndroidRuntime
frameworks/base/core/jni/AndroidRuntime.cpp
2-1. AndroidRuntime::start(const char* className, const Vector<String8>& options)
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");//初始化字符串startSystemServer瞎抛,
//判斷從app_main傳遞過來的參數(shù)是否帶有該參數(shù)
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {//判斷參數(shù)
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
const char* rootDir = getenv("ANDROID_ROOT");//獲取ANDROID_ROOT環(huán)境變量,
//adb shell 到手機里面echo $ANDROID_ROOT却紧,得出該環(huán)境變量為 "/system"
if (rootDir == NULL) {//第一次進來為空婿失,先設(shè)置rootDir 為"/system"
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) { //核心,啟動虛擬機啄寡,該方法中會配置各種JVM參數(shù)豪硅,
//最終會調(diào)用JNI_CreateJavaVM方法創(chuàng)建JVM
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {//核心中的核心,注冊JNI方法,什么Binder,各種核心庫的JNI基本都在這里注冊
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);//className從app_main.cpp傳遞過來的闻察,
//為"com.android.internal.os.ZygoteInit"许蓖,
//toSlashClassName將className中的字符串替換為"/"來滿足FindClass(slashClassName)
//對參數(shù)的需求來獲取java class 對象
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); //獲取Java層ZygoteInit的"main"方法ID
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);//執(zhí)行Java層ZygoteInit "main"方法仰担,
//終于看到了指向Java層的曙光伴嗡;
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
本來我們應(yīng)該繼續(xù)往下跳轉(zhuǎn)到ZygoteInit.java的main方法婉支,但是我覺得AndroidRuntime中有幾個重要的方法需要記住帆卓,在此先說說稽穆,Java層的ZygoteInit放到下一篇再說:
2-2. int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
/*
* Start the Dalvik Virtual Machine.
*
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
* CAUTION: when adding options in here, be careful not to put the
* char buffer inside a nested scope. Adding the buffer to the
* options using mOptions.add() does not copy the buffer, so if the
* buffer goes out of scope the option may be overwritten. It's best
* to put the buffer at the top of the function so that it is more
* unlikely that someone will surround it in a scope at a later time
* and thus introduce a bug.
*
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
int result = -1;
JavaVMInitArgs initArgs;
char zygoteMaxFailedBootsBuf[sizeof("-XzygoteMaxFailedBoots")-1 + PROPERTY_VALUE_MAX];
char propBuf[PROPERTY_VALUE_MAX];
char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
char extraOptsBuf[PROPERTY_VALUE_MAX];
char voldDecryptBuf[PROPERTY_VALUE_MAX];
enum {
kEMDefault,
kEMIntPortable,
kEMIntFast,
kEMJitCompiler,
} executionMode = kEMDefault;
char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX];
char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX];
char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX];
char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX];
char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX];
char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 +
PROPERTY_VALUE_MAX];
char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX];
char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + PROPERTY_VALUE_MAX];
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX];
char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX];
char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
......
property_get("dalvik.vm.checkjni", propBuf, "");
......
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
......
}
/*
* Reads a "property" into "buffer" with a default of "defaultArg". If
* the property is non-empty, it is treated as a runtime option such
* as "-Xmx32m".
*
* The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx".
*
* If an argument is found, it is added to mOptions.
*
* If an option is found, it is added to mOptions and true is
* returned. Otherwise false is returned.
*/
bool AndroidRuntime::parseRuntimeOption(const char* property,
char* buffer,
const char* runtimeArg,
const char* defaultArg)
{
strcpy(buffer, runtimeArg);
size_t runtimeArgLen = strlen(runtimeArg);
property_get(property, buffer+runtimeArgLen, defaultArg);
if (buffer[runtimeArgLen] == '\0') {
return false;
}
addOption(buffer);
return true;
}
這里對于Java Dalvik 參數(shù)配置冠王,大部分都是通過獲取系統(tǒng)屬性來賦值;對此不需要詳解舌镶;
2-3. int AndroidRuntime::startReg(JNIEnv* env)
/*
* Register android native functions with the VM.
*/
/*static*/
int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {//注冊JNI方法柱彻,很重要,gRegJNI是方法表
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
2-4. gRegJNI 方法表
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_graphics_Graphics),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_view_RenderNode),
REG_JNI(register_android_view_RenderNodeAnimator),
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
REG_JNI(register_android_view_SurfaceSession),
REG_JNI(register_android_view_TextureView),
REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_EGL14),
REG_JNI(register_android_opengl_jni_EGLExt),
REG_JNI(register_android_opengl_jni_GLES10),
REG_JNI(register_android_opengl_jni_GLES10Ext),
REG_JNI(register_android_opengl_jni_GLES11),
REG_JNI(register_android_opengl_jni_GLES11Ext),
REG_JNI(register_android_opengl_jni_GLES20),
REG_JNI(register_android_opengl_jni_GLES30),
REG_JNI(register_android_opengl_jni_GLES31),
REG_JNI(register_android_opengl_jni_GLES31Ext),
REG_JNI(register_android_graphics_Bitmap),
REG_JNI(register_android_graphics_BitmapFactory),
REG_JNI(register_android_graphics_BitmapRegionDecoder),
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_CanvasProperty),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_FontFamily),
REG_JNI(register_android_graphics_Movie),
REG_JNI(register_android_graphics_NinePatch),
REG_JNI(register_android_graphics_Paint),
REG_JNI(register_android_graphics_Path),
REG_JNI(register_android_graphics_PathMeasure),
REG_JNI(register_android_graphics_PathEffect),
REG_JNI(register_android_graphics_Picture),
REG_JNI(register_android_graphics_PorterDuff),
REG_JNI(register_android_graphics_Rasterizer),
REG_JNI(register_android_graphics_Region),
REG_JNI(register_android_graphics_Shader),
REG_JNI(register_android_graphics_SurfaceTexture),
REG_JNI(register_android_graphics_Typeface),
REG_JNI(register_android_graphics_pdf_PdfRenderer),
REG_JNI(register_android_database_CursorWindow),
REG_JNI(register_android_database_SQLiteConnection),
REG_JNI(register_android_database_SQLiteGlobal),
REG_JNI(register_android_database_SQLiteDebug),
REG_JNI(register_android_os_Debug),
REG_JNI(register_android_os_FileObserver),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_SELinux),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement),
REG_JNI(register_android_hardware_camera2_DngCreator),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_SerialPort),
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_media_ToneGenerator),
REG_JNI(register_android_opengl_classes),
REG_JNI(register_android_server_NetworkManagementSocketTagger),
REG_JNI(register_android_app_ActivityThread),
REG_JNI(register_android_app_NativeActivity),
REG_JNI(register_android_view_InputChannel),
REG_JNI(register_android_view_InputEventReceiver),
REG_JNI(register_android_view_InputEventSender),
REG_JNI(register_android_view_InputQueue),
REG_JNI(register_android_view_KeyEvent),
};
限于篇幅原因我刪除了很多餐胀,這里注冊的這些JNI方法都很重要很重要很重要哟楷,比如Binder,Camera否灾,EGL 等等卖擅;
這篇文章描述有點雜,貼的代碼中有很多注釋墨技,很多是Google 原生的注釋我沒刪除惩阶,因為我覺得這些注釋簡單明了。
總結(jié):app_process進程主要是根據(jù)init.rc腳本來設(shè)置參數(shù)扣汪,然后調(diào)用到Java層的ZygoteInit断楷;