Android Zygote进程源码分析

https://blog.csdn.net/xichangbao/article/details/53104810

一 app_process64

Zygote所对应的可执行文件是/system/bin/app_process64
Zygote的代码路径frameworks/base/cmds/app_process

1.0 app_process64
init.rc中import /init.${ro.zygote}.rc,而ro.zygote=zygote64_32
init.zygote64_32 .rc的内容如下
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
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
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks

64位系统为了兼容32位应用程序,将同时启动zygote64和zygote,下面以zygote64为例分析。

1.1 app_process64的main函数
app_process64的入口函数是:app_main.cpp的main函数
参数是: -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { // 用来防止动态改变进程的权限
// Older kernels don’t understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don’t die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL(“PR_SET_NO_NEW_PRIVS failed: %s”, strerror(errno));
return 12;
}
}

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // 创建AppRuntime,android运行时环境
// Process command line arguments
// ignore argv[0]
argc--; // argv[0]等程序名称,不需要解析,因此跳过
argv++;

// 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] != '-') { // i=1时,argv[1]=/system/bin // 跳出for循环
        break;
    }
    if (argv[i][1] == '-' && argv[i][2] == 0) {
        ++i; // Skip --.
        break;
    }
    runtime.addOption(strdup(argv[i])); // 当i=0时,将-Xzygote加入到runtime的mOptions中
}

// 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后i=2
while (i < argc) { // 解析启动参数 // /init.${ro.zygote}.rc文件中为zygote进程设置的启动参数是-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    const char* arg = argv[i++];
    if (strcmp(arg, "--zygote") == 0) {
        zygote = true;
        niceName = ZYGOTE_NICE_NAME; // 对于64位系统nice_name为zygote64
    } 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;
    }
}

// 从while循环出来后,i等于4,zygote为true,niceName为zygote64,startSystemServer为true,application为false,className为null
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 { // Zygote
    // We're in zygote mode.
    maybeCreateDalvikCache(); // 创建/data/dalvik-cache

    if (startSystemServer) {
        args.add(String8("start-system-server")); // 将start-system-server添加到args中
    }

    char prop[PROP_VALUE_MAX];
    if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { // ro.product.cpu.abilist64=arm64-v8a
        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); // --abi-list=arm64-v8a
    args.add(abiFlag); // 将--abi-list=arm64-v8a添加到args中

    // In zygote mode, pass all remaining arguments to the zygote
    // main() method.
    for (; i < argc; ++i) {
        args.add(String8(argv[i])); // 将--socket-name=zygote添加到args中
    }
}

if (!niceName.isEmpty()) { // 修改程序名称
    runtime.setArgv0(niceName.string());
    set_process_name(niceName.string()); // 对Zygote而言就是将程序名称app_process64改为zygote64
}

// 调用AppRuntime的start方法
if (zygote) { // zygote
    InitializeNativeLoader(); // system/core/libnativeloader/native_loader.cpp
   runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // 调用AndroidRuntime的start()方法
} 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;
}

}

app_process64的main函数比较简单,注释也比较详细。

1.2 maybeCreateDalvikCache

static void maybeCreateDalvikCache() {
#if defined(aarch64)
static const char kInstructionSet[] = “arm64”; // 指令集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) && !defined(LP64)
static const char kInstructionSet[] = “mips”;
#elif defined (mips) && defined(LP64)
static const char kInstructionSet[] = “mips64”;
#else
#error “Unknown instruction set”
#endif
const char* androidRoot = getenv(“ANDROID_DATA”); // ANDROID_DATA=/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/arm64
LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
        "Error constructing dalvik cache : %s", strerror(errno));

int result = mkdir(dalvikCacheDir, 0711); // 创建虚拟机的cache目录/data/dalvik-cache/arm64,权限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); // 改变/data/dalvik-cache/arm64的所有权,将owner和group都设为root
LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));

result = chmod(dalvikCacheDir, 0711); // 设置权限0711
LOG_ALWAYS_FATAL_IF((result < 0),
        "Error changing dalvik-cache permissions : %s", strerror(errno));

}

1.3 InitializeNativeLoader

定义在system/core/libnativeloader/native_loader.cpp中
static std::mutex g_namespaces_mutex;
static LibraryNamespaces* g_namespaces = new LibraryNamespaces;

void InitializeNativeLoader() {
#if defined(ANDROID)
std::lock_guardstd::mutex guard(g_namespaces_mutex);
g_namespaces->Initialize();
#endif
}

二 AndroidRuntime

2.0 start

AndroidRuntime::start主要完成两项工作:1 启动虚拟机 ,2 调用className类的static void main(String args[])方法
定义在frameworks/base/core/jni/AndroidRuntime.cpp中
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote) // className为com.android.internal.os.ZygoteInit,options为start-system-server,–abi-list=arm64-v8a,–socket-name=zygote,zygote为true
{
ALOGD(“>>>>>> START %s uid %d <<<<<<\n”,
className != NULL ? className : “(unknown)”, getuid());

static const String8 startSystemServer("start-system-server");

/*
 * '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) {
       /* 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=/system
if (rootDir == NULL) {
    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); // 初始化jni接口
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { // 启动虚拟机
    return;
}
onVmCreated(env); // 空函数

/*
 * Register android functions.
 */
if (startReg(env) < 0) { // 注册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); //  strArray[0] = "com.android.internal.os.ZygoteInit"

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);
}
// strArray[1] = "start-system-server",strArray[2] = "--abi-list=arm64-v8a",strArray[3] = "--socket-name=zygote"

 /*
 * Start VM.  This thread becomes the main thread of the VM, and will
 * not return until the VM exits.
 */
char* slashClassName = toSlashClassName(className); // 将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
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"); // 查找ZygoteInit类的main()方法
    if (startMeth == NULL) {
        ALOGE("JavaVM unable to find main() in '%s'\n", className);
        /* keep going */
    } else {
        env->CallStaticVoidMethod(startClass, startMeth, strArray); // 调用ZygoteInit的main()方法,进入Java世界

#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName); // 释放slashClassName的内存空间

ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK) // 取消线程与jvm关联
    ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0) // 销毁Java虚拟机并回收资源
    ALOGW("Warning: VM did not shut down cleanly\n");

}

2.1 startVm

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
JavaVMInitArgs initArgs;
char propBuf[PROPERTY_VALUE_MAX];
char stackTraceFileBuf[sizeof(“-Xstacktracefile:”)-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 usejitOptsBuf[sizeof(“-Xusejit:”)-1 + PROPERTY_VALUE_MAX];
char jitmaxsizeOptsBuf[sizeof(“-Xjitmaxsize:”)-1 + PROPERTY_VALUE_MAX];
char jitinitialsizeOptsBuf[sizeof(“-Xjitinitialsize:”)-1 + PROPERTY_VALUE_MAX];
char jitthresholdOptsBuf[sizeof(“-Xjitthreshold:”)-1 + PROPERTY_VALUE_MAX];
char jitprithreadweightOptBuf[sizeof(“-Xjitprithreadweight:”)-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 cachePruneBuf[sizeof(“-Xzygote-max-boot-retry=”)-1 + 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 dex2oatThreadsBuf[sizeof(“-j”)-1 + PROPERTY_VALUE_MAX];
char dex2oatThreadsImageBuf[sizeof(“-j”)-1 + PROPERTY_VALUE_MAX];
char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
char dex2oat_isa_variant[sizeof(“–instruction-set-variant=”) -1 + PROPERTY_VALUE_MAX];
char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
char dex2oat_isa_features[sizeof(“–instruction-set-features=”) -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 localeOption[sizeof(“-Duser.locale=”) + PROPERTY_VALUE_MAX];
char lockProfThresholdBuf[sizeof(“-Xlockprofthreshold:”)-1 + PROPERTY_VALUE_MAX];
char nativeBridgeLibrary[sizeof(“-XX:NativeBridge=”) + PROPERTY_VALUE_MAX];
char cpuAbiListBuf[sizeof(“–cpu-abilist=”) + PROPERTY_VALUE_MAX];
char methodTraceFileBuf[sizeof(“-Xmethod-trace-file:”) + PROPERTY_VALUE_MAX];
char methodTraceFileSizeBuf[sizeof(“-Xmethod-trace-file-size:”) + PROPERTY_VALUE_MAX];
char fingerprintBuf[sizeof(“-Xfingerprint:”) + PROPERTY_VALUE_MAX];

bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, ""); // JNI检测功能,用于native层调用jni函数时进行常规检测
if (strcmp(propBuf, "true") == 0) {
    checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
    /* property is neither true nor false; fall back on kernel parameter */
    property_get("ro.kernel.android.checkjni", propBuf, "");
    if (propBuf[0] == '1') {
        checkJni = true;
    }
}
ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
    /* extended JNI checking */
    addOption("-Xcheck:jni");

    /* with -Xcheck:jni, this provides a JNI function call trace */
    //addOption("-verbose:jni");
}

property_get("dalvik.vm.execution-mode", propBuf, "");
if (strcmp(propBuf, "int:portable") == 0) {
    executionMode = kEMIntPortable;
} else if (strcmp(propBuf, "int:fast") == 0) {
    executionMode = kEMIntFast;
} else if (strcmp(propBuf, "int:jit") == 0) {
    executionMode = kEMJitCompiler;
}

parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:"); // -Xstacktracefile:/data/anr/traces.txt // Java虚拟机接收到SIGQUIT(Ctrl-\或者kill -3)信号之后,会将所有线程的调用堆栈输出输出到/data/anr/traces.txt

strcpy(jniOptsBuf, "-Xjniopts:");
if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) { // JNI检测选项
    ALOGI("JNI options: '%s'\n", jniOptsBuf);
}

/* route exit() to our handler */
addOption("exit", (void*) runtime_exit); // 添加Java虚拟机选项,当Java虚拟机退出时执行runtime_exit方法

/* route fprintf() to our handler */
addOption("vfprintf", (void*) runtime_vfprintf); // 当Java虚拟机调用vfprintf时,调用runtime_vfprintf方法

/* register the framework-specific "is sensitive thread" hook */
addOption("sensitiveThread", (void*) runtime_isSensitiveThread);

/* enable verbose; standard options are { jni, gc, class } */
//addOption("-verbose:jni");
addOption("-verbose:gc");
//addOption("-verbose:class");

/*
 * The default starting and maximum size of the heap.  Larger
 * values should be specified in a product property override.
 */
parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m"); // 设置虚拟机的heapsize,默认为16M

parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
parseRuntimeOption("dalvik.vm.heaptargetutilization",
                   heaptargetutilizationOptsBuf,
                   "-XX:HeapTargetUtilization=");

/*
 * JIT related options.
 */
parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:");
parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");
parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");
parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");
parseRuntimeOption("dalvik.vm.jitprithreadweight",
                   jitprithreadweightOptBuf,
                   "-Xjitprithreadweight:");

property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
  addOption("-XX:LowMemoryMode");
}

parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");

/*
 * Enable debugging only for apps forked from zygote.
 * Set suspend=y to pause during VM init and use android ADB transport.
 */
if (zygote) {
  addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"); //
}

parseRuntimeOption("dalvik.vm.lockprof.threshold",
                   lockProfThresholdBuf,
                   "-Xlockprofthreshold:");

if (executionMode == kEMIntPortable) {
    addOption("-Xint:portable");
} else if (executionMode == kEMIntFast) {
    addOption("-Xint:fast");
} else if (executionMode == kEMJitCompiler) {
    addOption("-Xint:jit");
}

// If we are booting without the real /data, don't spend time compiling.
property_get("vold.decrypt", voldDecryptBuf, "");
bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
                         (strcmp(voldDecryptBuf, "1") == 0));

// Extra options for boot.art/boot.oat image generation.
parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
                           "-Xms", "-Ximage-compiler-option");
parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
                           "-Xmx", "-Ximage-compiler-option");
if (skip_compilation) {
    addOption("-Ximage-compiler-option");
    addOption("--compiler-filter=verify-none");
} else {
    parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
                        "--compiler-filter=", "-Ximage-compiler-option");
}

// Make sure there is a preloaded-classes file.
if (!hasFile("/system/etc/preloaded-classes")) {
    ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
          strerror(errno));
    return -1;
}
addOption("-Ximage-compiler-option");
addOption("--image-classes=/system/etc/preloaded-classes");

// If there is a compiled-classes file, push it.
if (hasFile("/system/etc/compiled-classes")) {
    addOption("-Ximage-compiler-option");
    addOption("--compiled-classes=/system/etc/compiled-classes");
}

property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");

// Extra options for DexClassLoader.
parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
                           "-Xms", "-Xcompiler-option");
parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
                           "-Xmx", "-Xcompiler-option");
if (skip_compilation) {
    addOption("-Xcompiler-option");
    addOption("--compiler-filter=verify-none");

    // We skip compilation when a minimal runtime is brought up for decryption. In that case
    // /data is temporarily backed by a tmpfs, which is usually small.
    // If the system image contains prebuilts, they will be relocated into the tmpfs. In this
    // specific situation it is acceptable to *not* relocate and run out of the prebuilts
    // directly instead.
    addOption("--runtime-arg");
    addOption("-Xnorelocate");
} else {
    parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
                        "--compiler-filter=", "-Xcompiler-option");
}
parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");
parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
                    "-Ximage-compiler-option");

// The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
// pass the instruction-set-features/variant as an image-compiler-option.
// TODO: Find a better way for the instruction-set.

#if defined(arm)
constexpr const char* instruction_set = “arm”;
#elif defined(aarch64)
constexpr const char* instruction_set = “arm64”;
#elif defined(mips) && !defined(LP64)
constexpr const char* instruction_set = “mips”;
#elif defined(mips) && defined(LP64)
constexpr const char* instruction_set = “mips64”;
#elif defined(i386)
constexpr const char* instruction_set = “x86”;
#elif defined(x86_64)
constexpr const char* instruction_set = “x86_64”;
#else
constexpr const char* instruction_set = “unknown”;
#endif
// Note: it is OK to reuse the buffer, as the values are exactly the same between
// * compiler-option, used for runtime compilation (DexClassLoader)
// * image-compiler-option, used for boot-image compilation on device

// Copy the variant.
sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                    "--instruction-set-variant=", "-Ximage-compiler-option");
parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                    "--instruction-set-variant=", "-Xcompiler-option");
// Copy the features.
sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                    "--instruction-set-features=", "-Ximage-compiler-option");
parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                    "--instruction-set-features=", "-Xcompiler-option");


property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");

/* extra options; parse this late so it overrides others */
property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
parseExtraOpts(extraOptsBuf, NULL);

/* Set the properties for locale */
{
    strcpy(localeOption, "-Duser.locale=");
    const std::string locale = readLocale();
    strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX);
    addOption(localeOption);
}

// Trace files are stored in /data/misc/trace which is writable only in debug mode.
property_get("ro.debuggable", propBuf, "0");
if (strcmp(propBuf, "1") == 0) {
    property_get("dalvik.vm.method-trace", propBuf, "false");
    if (strcmp(propBuf, "true") == 0) {
        addOption("-Xmethod-trace");
        parseRuntimeOption("dalvik.vm.method-trace-file",
                           methodTraceFileBuf,
                           "-Xmethod-trace-file:");
        parseRuntimeOption("dalvik.vm.method-trace-file-siz",
                           methodTraceFileSizeBuf,
                           "-Xmethod-trace-file-size:");
        property_get("dalvik.vm.method-trace-stream", propBuf, "false");
        if (strcmp(propBuf, "true") == 0) {
            addOption("-Xmethod-trace-stream");
        }
    }
}

// Native bridge library. "0" means that native bridge is disabled.
property_get("ro.dalvik.vm.native.bridge", propBuf, "");
if (propBuf[0] == '\0') {
    ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
} else if (strcmp(propBuf, "0") != 0) {
    snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
             "-XX:NativeBridge=%s", propBuf);
    addOption(nativeBridgeLibrary);
}

#if defined(LP64)
const char* cpu_abilist_property_name = “ro.product.cpu.abilist64”;
#else
const char* cpu_abilist_property_name = “ro.product.cpu.abilist32”;
#endif // defined(LP64)
property_get(cpu_abilist_property_name, propBuf, “”);
if (propBuf[0] == ‘\0’) {
ALOGE(“%s is not expected to be empty”, cpu_abilist_property_name);
return -1;
}
snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), “–cpu-abilist=%s”, propBuf);
addOption(cpuAbiListBuf); // ABI: arm64-v8a

// Dalvik-cache pruning counter.
parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
                   "-Xzygote-max-boot-retry=");

/*
 * When running with debug.generate-debug-info, add --generate-debug-info to
 * the compiler options so that the boot image, if it is compiled on device,
 * will include native debugging information.
 */
property_get("debug.generate-debug-info", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
    addOption("-Xcompiler-option");
    addOption("--generate-debug-info");
    addOption("-Ximage-compiler-option");
    addOption("--generate-debug-info");
}

/*
 * Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will
 * contain the fingerprint and can be parsed.
 */
parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");
// 以上代码主要是在读取dalvik.vm.* 属性然后设置Java虚拟机参数

initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;

/*
 * Initialize the VM.
 *
 * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
 * If this call succeeds, the VM is ready, and we can start issuing
 * JNI calls.
 */
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { // 创建Java虚拟机 // 最终调用的是art/runtime/java_vm_ext.cc中的JNI_CreateJavaVM函数
    ALOGE("JNI_CreateJavaVM failed\n");
    return -1;
}

return 0;

}

// art/runtime/java_vm_ext.cc中的JNI_CreateJavaVM函数
extern “C” jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
ScopedTrace trace(FUNCTION);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
if (IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
return JNI_EVERSION;
}
RuntimeOptions options;
for (int i = 0; i < args->nOptions; ++i) {
JavaVMOption* option = &args->options[i];
options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
}
bool ignore_unrecognized = args->ignoreUnrecognized;
if (!Runtime::Create(options, ignore_unrecognized)) { // 创建Runtime
return JNI_ERR;
}
Runtime* runtime = Runtime::Current();
bool started = runtime->Start(); // Runtime::start()
if (!started) {
delete Thread::Current()->GetJniEnv();
delete runtime->GetJavaVM();
LOG(WARNING) << “CreateJavaVM failed”;
return JNI_ERR;
}
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
}

2.2 startReg

/static/ int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME(“RegisterAndroidNatives”);
/*
* 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); // 设置线程创建方法为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); // 为200个局部引用创建堆栈

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { // 注册JNI函数,gRegJNI是一个全局数组,存放上百个需要注册的jni函数
    env->PopLocalFrame(NULL);
    return -1;
}
env->PopLocalFrame(NULL); // 销毁堆栈

//createJavaThread("fubar", quickTest, (void*) "hello");

return 0;

}

三 ZygoteInit

3.0 main

定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中
public static void main(String argv[]) {
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, “ZygoteInit”); // 开始Systrace追踪ZygoteInit
RuntimeInit.enableDdms(); // 使能DDMS功能 // Dalvik Debug Monitor Service虚拟机调试服务
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start(); // 启动性能统计

    boolean startSystemServer = false;
    String socketName = "zygote";
    String abiList = null;
    for (int i = 1; i < argv.length; i++) {
        if ("start-system-server".equals(argv[i])) {
            startSystemServer = true;
        } else if (argv[i].startsWith(ABI_LIST_ARG)) {
            abiList = argv[i].substring(ABI_LIST_ARG.length());
        } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
            socketName = argv[i].substring(SOCKET_NAME_ARG.length());
        } else {
            throw new RuntimeException("Unknown command line argument: " + argv[i]);
        }
    }
    
    // 从for循环出来后,startSystemServer为true,abiList为arm64-v8a,socketName为zygote

    if (abiList == null) {
        throw new RuntimeException("No ABI list supplied.");
    }

    registerZygoteSocket(socketName); // 注册zygote使用的socket
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload"); // 开始Systrace追踪ZygotePreload
    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
        SystemClock.uptimeMillis());
    preload(); // 预加载类和资源 // 这里可以进行优化以提升开机速度
    EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
        SystemClock.uptimeMillis());
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // 停止Systrace追踪ZygotePreload

    // Finish profiling the zygote initialization.
    SamplingProfilerIntegration.writeZygoteSnapshot(); // 结束性能统计并生成结果文件,保存在/data/snapshots

    // Do an initial gc to clean up after startup
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC"); // 开始Systrace追踪PostZygoteInitGC
    gcAndFinalize(); // 强制垃圾回收
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // 停止Systrace追踪PostZygoteInitGC

    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // 停止Systrace追踪ZygoteInit

    // Disable tracing so that forked processes do not inherit stale tracing tags from
    // Zygote.
    Trace.setTracingEnabled(false); // 禁止Systrace追踪 

    // Zygote process unmounts root storage spaces.
    Zygote.nativeUnmountStorageOnInit(); // 空函数

    if (startSystemServer) {
        startSystemServer(abiList, socketName); // 启动system_server进程 // 单独分析
    }

    Log.i(TAG, "Accepting command socket connections");
    runSelectLoop(abiList); // Zygote无限循环等待创建进程的请求

    closeServerSocket(); // 退出时关闭服务器端Socket
} catch (MethodAndArgsCaller caller) {
    caller.run(); // 在system_serer进程中,以反射方式调用SystemServer类的main方法
} catch (RuntimeException ex) {
    Log.e(TAG, "Zygote died with exception", ex);
    closeServerSocket();
    throw ex;
}

}

3.1 registerZygoteSocket

private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; // 获取socket描述字符串 // ANDROID_SOCKET_zygote
try {
String env = System.getenv(fullSocketName); // 从环境变量中获取ANDROID_SOCKET_zygote
fileDesc = Integer.parseInt(env); // 获取socket文件描述符
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}

    try {
        FileDescriptor fd = new FileDescriptor();
        fd.setInt$(fileDesc);
        sServerSocket = new LocalServerSocket(fd);  // 创建服务端Socket
    } catch (IOException ex) {
        throw new RuntimeException(
                "Error binding to local socket '" + fileDesc + "'", ex);
    }
}

}

public LocalServerSocket(FileDescriptor fd) throws IOException
{
impl = new LocalSocketImpl(fd);
impl.listen(LISTEN_BACKLOG);
localAddress = impl.getSockAddress();
}

3.2 preload

static void preload() {
Log.d(TAG, “begin preload”);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, “PreloadClasses”);
preloadClasses(); // 预加载/system/etc/preloaded-classes文件中的类
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, “PreloadResources”);
preloadResources(); //预加载drawable和color资源
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, “PreloadOpenGL”);
preloadOpenGL(); // 预加载OpenGL
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
preloadSharedLibraries(); // 预加载"android",“compiler_rt”,"jnigraphics"共享库
preloadTextResources(); //预加载text资源
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote(); // 预加载WebView库
Log.d(TAG, “end preload”);
}

3.3 gcAndFinalize

/package/ static void gcAndFinalize() {
final VMRuntime runtime = VMRuntime.getRuntime();

/* runFinalizationSync() lets finalizers be called in Zygote,
 * which doesn't have a HeapWorker thread.
 */
System.gc();
runtime.runFinalizationSync();
System.gc();

}

3.4 runSelectLoop

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();

fds.add(sServerSocket.getFileDescriptor()); // sServerSocket就是之前registerZygoteSocket建立的服务器端Socket
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; // POLLIN表示有数据可读
    }
    try {
        Os.poll(pollFds, -1); // 监视pollFds中的文件描述符
    } 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) { // i等于0时,建立连接
            ZygoteConnection newPeer = acceptCommandPeer(abiList); // 接受新的socket连接并创建一个ZygoteConnection
            peers.add(newPeer);
            fds.add(newPeer.getFileDesciptor()); // 将socket连接的文件描述符添加到fds,再下一个while循环开始监视
        } else { // i不等于0时,接收数据,并处理
            boolean done = peers.get(i). runOnce();  // 调用对应ZygoteConnection的runOnce
            if (done) {
                peers.remove(i);
                fds.remove(i);
            }
        }
    }
}

}

3.5 closeServerSocket

static void closeServerSocket() {
try {
if (sServerSocket != null) {
FileDescriptor fd = sServerSocket.getFileDescriptor();
sServerSocket.close();
if (fd != null) {
Os.close(fd);
}
}
} catch (IOException ex) {
Log.e(TAG, “Zygote: error closing sockets”, ex);
} catch (ErrnoException ex) {
Log.e(TAG, “Zygote: error closing descriptor”, ex);
}

sServerSocket = null;

}

以下内容摘录自《深入理解 Android 卷I》关于 Zygote的总结
Zygote是创建Android系统中Java世界的盘古,它创建了第一个Java虚拟机,同时它又是女娲,它成功地繁殖了framework的核心system_server进程。做为Java语言的受益者,我们理应回顾一下Zygote创建Java世界的步骤:
· 第一天:创建AppRuntime对象,并调用它的start。此后的活动则由AppRuntime来控制。
· 第二天:调用startVm创建Java虚拟机,然后调用startReg来注册JNI函数。
· 第三天:通过JNI调用com.android.internal.os.ZygoteInit类的main函数,从此进入了Java世界。然而在这个世界刚开创的时候,什么东西都没有。
· 第四天:调用registerZygoteSocket。通过这个函数,它可以响应子孙后代的请求。同时Zygote调用preloadClasses和preloadResources,为Java世界添砖加瓦。
· 第五天:Zygote觉得自己工作压力太大,便通过调用startSystemServer分裂一个子进程system_server来为Java世界服务。
· 第六天:Zygote完成了Java世界的初创工作,它已经很满足了。下一步该做的就是调用runSelectLoopMode后,便沉沉地睡去了。
· 以后的日子:Zygote随时守护在我们的周围,当接收到子孙后代的请求时,它会随时醒来,为它们工作。

如果让我来做对比,我更愿意将Init比作盘古,Zygote比作女娲,SystemServer比作伏羲。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值