Android10 Framework—Zygote-4.AppProcess启动Class

51 阅读2分钟

在前面的文章分析过/system/bin/app_process64可以打开指定的className,使用示例如下:

app_process -Djava.class.path=/data/local/tmp/Test.dex /data/test com.zygote.Test
  • -Djava.class.p**:属于 [java-options],这些参数会传给虚拟机,并且参数必须以 - 开头,一旦遇到非 - 或者 --,表示 [java-options] 结束;
  • /data/test:属于 cmd-dir,程序的运行目录,随便指定即可,文件操作时会以此为当前路径,大多运行在 /system/bin 下;
  • com.zygote.Test:属于 start-class-name,声明入口类的名称,有包名的话需要加上包名;

当指定className时会调用com.android.internal.os.RuntimeInit.main

@UnsupportedAppUsage
public static final void main(String[] argv) {
    enableDdms();
    if (argv.length == 2 && argv[1].equals("application")) {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
        redirectLogStreams();
    } else {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
    }

    commonInit();

    /*
     * Now that we're running in interpreted code, call back into native code
     * to run the system.
     */
    nativeFinishInit();

    if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
}

commonInit用于执行一些通用配置的初始化:

  • 设置 KillApplicationHandler 为默认的 UncaughtExceptionHandler;
  • 设置时区;
  • 设置 http.agent 属性,用于 HttpURLConnection;
  • 重置 Android 的 Log 系统;
  • 通过 NetworkManagementSocketTagger 设置 socket 的 tag,用于流量统计;
//frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeFinishInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onStarted();
}

gCurRuntime就是前面创建的AppRuntime实例,onStarted在AppRuntime进行了实现。

virtual void onStarted()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();

    AndroidRuntime* ar = AndroidRuntime::getRuntime();
    ar->callMain(mClassName, mClass, mArgs);

    IPCThreadState::self()->stopProcess();
    hardware::IPCThreadState::self()->stopProcess();
}
  • mClassName就是前面实例中的com.zygote.Test类
  • mClass是mClassName的Class
status_t AndroidRuntime::callMain(const String8& className, jclass clazz,
    const Vector<String8>& args)
{
    JNIEnv* env;
    jmethodID methodId;

    ALOGD("Calling main entry %s", className.string());

    env = getJNIEnv();
    if (clazz == NULL || env == NULL) {
        return UNKNOWN_ERROR;
    }

    methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
    if (methodId == NULL) {
        ALOGE("ERROR: could not find method %s.main(String[])\n", className.string());
        return UNKNOWN_ERROR;
    }

    /*
     * We want to call main() with a String array with our arguments in it.
     * Create an array and populate it.
     */
    jclass stringClass;
    jobjectArray strArray;

    const size_t numArgs = args.size();
    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(numArgs, stringClass, NULL);

    for (size_t i = 0; i < numArgs; i++) {
        jstring argStr = env->NewStringUTF(args[i].string());
        env->SetObjectArrayElement(strArray, i, argStr);
    }

    env->CallStaticVoidMethod(clazz, methodId, strArray);
    return NO_ERROR;
}

callMain实际上就是通过反射调用com.zygote.Test.main方法。