首页 > 其他分享 >02-DALVIK虚拟机启动过程

02-DALVIK虚拟机启动过程

时间:2022-11-07 16:48:35浏览次数:82  
标签:02 调用 DALVIK 虚拟机 Zygote parsedArgs 进程 Android android

2.1 init.rc启动脚本

Android系统在启动时,第一个启动的进程就是init进程,也就是我们说的一号进程,我们通过下图的ps命令可以看到init进程号为1。接着,init进程根据读取/init.rc文件中的配置创建并启动app_process进程,也就是我们的Zygote进程,其启动参数见下表所示。
init.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
…

上面的文件参数:
service表示Zygote进程是以服务的形式启动;
/system/bin/app_process表示它对应的文件位置;
后面四个选项就是Zygote进程的启动参数,其中—start-system-server表示Zygote进程启动完以后,需要马上运行SystemServer进程。
下面通过ps命令获取当前运行的进程信息

接着我们查看android源码/framework/base/cmds/app_process源码的入口函数main:

int main(int argc, char* const argv[])
{  …  AppRuntime runtime;
    …
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    const char* parentDir = NULL;
    const char* niceName = NULL;
    const char* className = NULL;
    
    while (i < argc) {
        const char* arg = argv[i++];
        if (!parentDir) {
            parentDir = arg;
        } else if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = "zygote";
        } 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 = arg + 12;
        } else {
            className = arg;
            break;
        }
    }
    …
   if (zygote) {
        //Zygote模式启动(创建Zygote进程和SystemServer进程)
        runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : "");
    } else if (className) {
        //非Zygote模式启动(创建应用程序的进程)
        // Remainder of args get passed to startup class main()
        runtime.mClassName = className;
        runtime.mArgC = argc - i;
        runtime.mArgV = argv + i;
        runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool");
    } 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.rc中Zygote的启动参数,我们知道arg参数中包含了” --zygote”和”--zygote --start-system-server”参数。所以,zygote和startSystemServer变量都为true。这表示Zygote进程启动完以后,会接着启动SystemServer进程。
从上面的代码,我们知道Zygote分两种模式启动,分别是Zygote模式和非Zygote模式。当处于Zygote模式时,系统会调用com.android.internal.os.ZygoteInit启动Zygote进程和SystemServer进程 ;当处于非Zygote模式时,系统会调用com.android.internal.os.RuntimeInit创建应用程序的进程。

2.2 创建Zygote进程

下面,我们来分析下Zygote进程的启动过程。我们看下AndroidRuntime类的start方法的关键代码:
位置:Android源码/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const char* options)
{  …  //加载libdvm.so  JniInvocation jni_invocation;  jni_invocation.Init(NULL);  …  //创建Dalvik虚拟机  if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    …
    //注册Android核心类的JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    …
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    jstring optionsStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(2, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    optionsStr = env->NewStringUTF(options);
    env->SetObjectArrayElement(strArray, 1, optionsStr);
    
    //调用com.android.internal.os.ZygoteInit的main方法(进入Java层)
    char* slashClassName = toSlashClassName(className);
    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");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
    …
}

该方法主要做了4个工作:

(1) 调用jni_invocation.Init()方法加载libdvm.so,并初始化JniInvocation类的成员

(2) 调用startVM()方法创建虚拟机,并初始化BootClassloader和加载/system/framework下的jar包

(3) 调用startReg()方法注册Android核心类的JNI方法

(4) 最后,通过JNI机制进入Java层的com.android.internal.os.ZygoteInit类的main方法,然后创建Zygote进程的Server端Socket,并启动SystemServer进程。

其关键流程如下图所示:

下面我们分别对上面4个工作进一步分析。

2.2.1 加载libdvm.so

参考[7]
位置:Android源码/libnativehelper/JniInvocation.cpp
我们看下JniInvocation类下的Init方法:

…
JniInvocation::JniInvocation() :
    handle_(NULL),
    JNI_GetDefaultJavaVMInitArgs_(NULL),
    JNI_CreateJavaVM_(NULL),
    JNI_GetCreatedJavaVMs_(NULL) {  LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");  jni_invocation_ = this;  }  …  bool JniInvocation::Init(const char* library) {      …  #ifdef HAVE_ANDROID_OS  static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib";  #endif  static const char* kLibraryFallback = "libdvm.so";   bool JniInvocation::Init(const char* library) {
#ifdef HAVE_ANDROID_OS
  char default_library[PROPERTY_VALUE_MAX];
  property_get(kLibrarySystemProperty, default_library, kLibraryFallback);
#else
  const char* default_library = kLibraryFallback;
#endif
  if (library == NULL) {
    library = default_library;
  }  …  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),"JNI_CreateJavaVM")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),"JNI_GetCreatedJavaVMs")) {
    return false;
  }
  return true;
}
我们首先看下JniInvocation类的定义,一共有4个成员,分别是handle_,用于保存dlopen加载libdvm.so后返回的文件句柄,以及JNI_GetDefaultJavaVMInitArgs_、JNI_CreateJavaVM_和JNI_GetCreatedJavaVMs_。
接下来继续分析Init方法。Init方法首先读取”persist.sys.dalvik.vm.lib”系统属性,该属性值可能是libdvm.so或libart.so,我们可以通过getprop命令后去persist.sys.dalvik.vm.lib属性的值,或者直接查看/system/build.prop文件。如下图,在Android4.4.3下默认还是libdvm.so,但用户可以通过在Settings=>Developer Options=>Select runtime来选择要Dalvik还是ART,如下图所示。而在Android5.0版本以后,则默认是ART。这里我们默认分析Dalvik。接下来,则调用dlopen加载libdvm.so,然后找到GetDefaultJavaVMInitArgs、CreateJavaVM和GetCreatedJavaVMs三个接口并赋值给JniInvocation类对应的3个成员。
我们可以看到,Init方法其实就是初始化JniInvocation类里面的成员,和初始化Dalvik虚拟机环境的。

获取persist.sys.dalvik.vm.lib属性的值。

TODO:了解JNI的环境

2.2.2 创建Dalvik虚拟机和初始化BootClassloader

完成JNI环境的初始化工作后,接着AndroidRuntime::start函数()调用startVM()方法创建虚拟机。我们看下startVM的代码:
位置:Android源码/base/core/jni/AndroidRuntime.cpp

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{      …
JavaVMInitArgs initArgs;
JavaVMOption opt;
…
property_get("dalvik.vm.checkjni", propBuf, "");
…
property_get("dalvik.vm.execution-mode", propBuf, "");
 …
property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
 …
property_get("dalvik.vm.check-dex-sum", propBuf, "");
…
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
…
property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
 …
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { … }     …
}

startVM方法先是读取系统属性并设置Dalvik虚拟机的各项参数,然后才调用JNI_CreateJavaVM方法真正去创建Dalvik虚拟机。这些参数我们也可以通过getprop命令去获取,如下图所示。

而JNI_CreateJavaVM方法正式livdvm.so中的函数。
位置:Android源码/dalvik/vm/jni.cpp。

jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
    …
    //初始化JavaVM变量
    JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt));
    pVM->funcTable = &gInvokeInterface;
    pVM->envList = NULL;
    dvmInitMutex(&pVM->envListLock);
    …
    //初始化JNI环境(初始化JNIEnv变量)
    JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
 
    //初始化Dalvik虚拟机
    gDvm.initializing = true;
    std::string status = dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
    gDvm.initializing = false;  …
}

JNI_CreateJavaVM首先初始化JavaVM和JNIEnv变量,完成JNI环境的初始化工作。接着调用创建虚拟机的核心方法dvmStartup()方法。我们看下dvmStartup()方法的源码:
位置:Android源码/dalvik/vm/Init.cpp

std::string dvmStartup(int argc, const char* const argv[],
        bool ignoreUnrecognized, JNIEnv* pEnv)
{   
     …
    //解析参数
    int cc = processOptions(argc, argv, ignoreUnrecognized);
    …
    //初始化BootClassLoader
    if (!dvmClassStartup()) {
        return "dvmClassStartup failed";
    }
}

dvmStartup首先对参数进行解析,然后做了很多其它工作,这里我们重点分析dvmClassStartup()方法,该方法初始化boot class loader,并加载bootclasspath路径下所有的jar包,也就是/system/framework下所有的类。也就是说Zygote进程加载了framework下所有的jar包,而由于app进程的创建是通过克隆Zygote进程的,所以说app也同样加载了所有的framework下的包。下图是BOOTCLASSPATH路径:

我们分析下dvmClassStartup()方法:
位置:Android源码/dalvik/vm/oo/Class.cpp

bool dvmClassStartup()
{      …
    //loadedClasses是哈希表,保存所有已经加载了的类
    gDvm.loadedClasses = dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
    …
    //加载bootclasspath路径下的所有jar包
    processClassPath(gDvm.bootClassPathStr, true);      …
}

gDvm全局变量的loadedClasses成员是哈希表,保存了所有加载到内存中的类。
dvmClassStartup方法调用processClassPath函数进行/system/framework目录下jar包的加载工作。该方法其实就是调用加载解析dex或jar包的方法,我们会在xxx章详细介绍。

2.2.3 framework层资源加载过程

TODO:分析processClassPath加载framework资源过程

3.2.4 通过反射进入ZygoteInit类的main方法

接下来我们分析com.android.internal.os.ZygoteInit的main方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    …
registerZygoteSocket();
    …
    if (argv[1].equals("start-system-server")) {
        startSystemServer();
    }
    …
    runSelectLoop();
    …
}

该main方法主要做了3件事:

(1) 注册创建Zygote进程的Server端Socket

(2) 启动SystemServer进程

(3) 进入消息循环,监听来自AMS发送过来的创建app进程的请求

2.3 创建Zygote进程Server端监听服务

    Zygote进程创建Server端Socket关键流程如下图所示:

我们从ZygoteInit类main方法的registerZygoteSocket函数源码源码开始分析:
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java

private static void registerZygoteSocket() {
    if (sServerSocket == null) {
        int fileDesc;
        try {
            String env = System.getenv(ANDROID_SOCKET_ENV);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            …
        }

        try {
            sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
        } catch (IOException ex) {
           …
        }
    }
}

可以看到registerZygoteSocket方法通过LocalServerSocket创建Server端Socket,并保存在ZygoteInit类的静态成员变量sServerSocket中。
接着,判断传递过来的参数是否包含”start-system-server”。我们从上面源码分析知道,Zygote启动的配置参数里面是包含该参数的。然后就调用startSystemServer来启动SystemServer进程。最后调用runSelectLoop方法进入消息循环,等待处理来自AMS发送过来的请求。
我们分析下runSelectLoop方法接收到创建app请求后的过程是怎样的。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java

private static void runSelectLoop() throws MethodAndArgsCaller {  …  while (true) {
    int index;
    …
    if (index < 0) {
            …
        } else if (index == 0) {
            …
        } else {
            boolean done;
            done = peers.get(index).runOnce();
            i…
        }
    …  }
}

这里,peers.get(index)返回的是ZygoteConnection对象,runSelectLoop方法实际上调用了ZygoteConnection对象的runOnce方法做进一步的处理。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteConnection.java

class ZygoteConnection { 
    …  
    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    …
    int pid = -1;
    …
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName);
   …
   if (pid == 0) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

             return true;
            }
    …  }
}

这里真正创建应用程序进程的操作是Zygote.forkAndSpecialize方法,当创建成功以后,就会调用handleChildProc来启动新创建的应用程序的进程。详细的分析我们会在3.5节讲解。

2.4 创建SystemServer进程

在3.2.3节,main入口函数调用了startSystemServer来启动SystemServer进程。SystemServer在这个过程中做了一件很重要的事情:

  • 启动重要的系统服务,如ActivityManagerService、PackageManagerService、WindowManagerService等。

它创建SystemServer的关键流程如下图所示。

下面我们一个个分析这些关键函数。

位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java

private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException {
    long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            …

            //调用forkSystemServer方法创建SystemServer进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        //启动SystemServer进程
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }

        return true;
}

首先创建参数数组,然后传递给forkSystemServer方法并创建SystemServer进程。创建成功后,接着调用handleSystemServerProcess方法来启动SystemServer进程。
SystemServer进程启动后,就会启动各种系统服务,如AMS、PMS、WMS等。
我们接着分析handleSystemServerProcess方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteInit.java

private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws ZygoteInit.MethodAndArgsCaller {
    …
    if (parsedArgs.invokeWith != null) {
        …
    } else {
        
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
    }
}

handleSystemServerProcess调用RuntimeInit类的zygoteInit方法。

位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

    redirectLogStreams();

    commonInit();
    nativeZygoteInit();

    applicationInit(targetSdkVersion, argv);
}
这里zygoteInit调用了一个重要的方法applicationInit方法。
位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
   …
   final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        …
    }

    // 调用com.android.server.SystemServer类的main方法
    invokeStaticMain(args.startClass, args.startArgs);
}

applicationInit调用invokeStaticMain方法通过反射的办法调用com.android.server.SystemServer类的main方法。
我们转到SystemServer类。
位置:Android源码/framework/base/services/java/com/android/server/SystemServer.java

public class SystemServer {
…
public static void main(String[] args) {
    …
    / Mmmmmm... more memory!
    dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

    // The system server has to run all of the time, so it needs to be
    // as efficient as possible with its memory usage.
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

    Environment.setUserRequired(true);

    System.loadLibrary("android_servers");

    Slog.i(TAG, "Entered the Android system server!");

    // Initialize native services.
    nativeInit();

    // This used to be its own separate thread, but now it is
    // just the loop we run on the main thread.
    ServerThread thr = new ServerThread();
    thr.initAndLoop();
}
}

main方法创建ServerThread对象并进入消息循环。

class ServerThread {
    …
public void initAndLoop() {
    …
    Looper.prepareMainLooper();
    …
    context = ActivityManagerService.main(factoryTest);
    …
    pm = PackageManagerService.main(context, installer,
                    factoryTest != SystemServer.FACTORY_TEST_OFF,
                    onlyCore);
    …
    contentService = ContentService.main(context,
                    factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
    …
    wm = WindowManagerService.main(context, power, display, inputManager,
                    wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                    !firstBoot, onlyCore);
    …
    Looper.loop();
}
}

    在initAndLoop方法里,通过调用各个系统服务类下的main方法创建完成关键系统服务的创建。然后调用Looper.loop()进入消息循环。

2.5 创建应用程序的进程

    结合2.3中的内容,创建应用程序进程的关系如下图所示。

ActivityManagerService和Zygote进程服务端通过LocalSocket和LocalServerSocket进行进程间通信,而两者通信的媒介正式/dev/socket/zygote文件。在AMS的Client端,startProcessLocked函数是发送请求的关键函数,而Zygote进程Server端的runSelectLoop函数则是接收AMS发送过来的请求的关键方法。

    回到3.1中android源码/framework/base/cmds/app_process的main函数入口,当处于非Zygote模式的时候创建的是应用程序的进程。然后通过3.3的分析我们知道,当我们点击桌面app的图标,启动一个应用程序的时候,AMS会调用startProcessLocked方法发送创建app进程的请求给Zygote进程Server端的Socket。

我们看下ActivityManagerService发送创建app进程请求的关键代码:
位置:Android源码/framework/base/services/java/com/android/server/am/ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) {
    …
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, null);
…
}

该方法会调用Process类的start静态方法实际上是通过创建LocalSocket跟3.2.4节中Zygote进程创建的Server端Socket进行通信,而Process.start传进来的参数正是要发送给Server端要创建的应用程序的相关参数信息。
根据3.2.4节我们知道,负责接收AMS发送过来请求的是ZygoteInit类的静态成员函数runSelectLoopMode方法,该方法最终会调用Zygote.forAndSpecialize()方法创建app进程,然后调用ZygoteConnection的handleChildProc函数成员来启动该app进程。
位置:Android源码/framework/base/core/java/com/android/internal/os/ZygoteConnection.java

class ZygoteConnection {  
    …  
    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
    …
    if (parsedArgs.runtimeInit) {
            if (parsedArgs.invokeWith != null) {
                …
            } else {
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs);
            }
        }  
    …  
  }
}

这里,parsedArgs.runtimeInit为true,parsedArgs.invokeWith为null。然后调用RuntimeInit的静态成员函数zygoteInit,这一步跟创建SystemServer进程的时候是一样的,不一样的是传递过去的参数。根据3.3的分析我们知道,zygoteInit方法接着会调用applicaitonInit方法,该方法中调用了invokeStaticMain方法,同样通过反射的办法调用上面传递过来的参数,去实际调用android.app.ActivityThread类的main入口函数。
位置:Android源码/framework/base/core/java/com/android/internal/os/RuntimeInit.java

private static void applicationInit(int targetSdkVersion, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
   …
   final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            …
        }

        // 调用android.app.ActivityThread类的main方法
        invokeStaticMain(args.startClass, args.startArgs);
}

从ActivityThread的main方法入口开始就是一个应用程序的启动过程。我们会在第二章的APP的启动过程做详细分析。
TODO:分析传递的参数

2.6 总结

现在我们用下面一幅图来梳理总结整个过程,对Dalvik的启动过程有一个全局的认识。

 

 

 

首先,Android系统在启动了init一号进程后,init进程就开始创建Zygote进程。Zygote进程主要负责两个工作:

(1) 启动SystemServer进程

(2) 创建应用程序的进程

Zygote进程在创建和初始化过程中,会调用dlopen去加载libdvm.so文件,并调用Class.cpp文件下的dvmClassStartup方法初始化BootClassloader类加载器,并加载bootclasspath,也就是/system/framework目录下的所有jar包。而由于应用程序进程的创建是通过克隆Zygote进程获得,所以,app进程中同样也加载了libdvm和/system/framework下的jar包。

然后Zygote进程会调用registerZygoteSocket()方法来创建一个Server端的Socket,然后调用runSelectLoopMode方法进入循环等待。这个Server端Socket主要负责接收ActivityManagerService发送过来的创建应用程序进程的请求,而AMS是通过调用startProcessLocked方法来发送请求的。当Zygote进程的Server端接收到来自AMS创建应用程序进程的请求后,就会调用forkAndSpecialize()方法创建。

 

参考:

[1] 《深入理解Android》(二)Java虚拟机Dalvik  http://www.infoq.com/cn/articles/android-in-depth-dalvik

[2] Android应用启动过程解析 http://zke1ev3n.me/2015/12/02/Android-%E5%BA%94%E7%94%A8%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E8%A7%A3%E6%9E%90/

[3]《Android系统源代码情景分析》第11、12章 Zygote和System进程的启动过程 和Android应用程序进程的启动过程http://blog.csdn.net/luoshengyang/article/details/6768304

[4]《Android Dalvivk虚拟机结构及机制剖析》第6章 Dalvik虚拟机执行流程详解

[5] Dalvik虚拟机的启动过程分析 http://blog.csdn.net/luoshengyang/article/details/8885792

[6] 理解Android虚拟机体系结构 http://android.jobbole.com/82413/

[7] Android虚拟机运行时无缝替换Dalvik虚拟机过程分析 http://blog.csdn.net/luoshengyang/article/details/18006645

[8] adb获取Android系统属性数据来源 http://blog.csdn.net/haixia_12/article/details/40857721

[9] Android应用程序进程启动过程的源代码分析 http://blog.csdn.net/luoshengyang/article/details/6747696

[10] Android进程通信套接字LocalSocket https://my.oschina.net/ososchina/blog/621761

标签:02,调用,DALVIK,虚拟机,Zygote,parsedArgs,进程,Android,android
From: https://www.cnblogs.com/domefy/p/16866463.html

相关文章

  • 2023 年企业如何按下数字化转型加速键?
    2022也接近尾声,即将迎来2023年,疫情或将持续而无法终结,市场环境或许有点捉摸不透,企业数字化转型依旧迫在眉睫,但依旧得慎重再慎重,企业实现数字化转型在理解什么是数字化转型......
  • 游记 CSP2022-J2/S2
    postedon2022-10-2822:41:08|under日志|sourceGD已经有代码了!游记写在代码里,搬过来吧。2022.10.29。GD-J00015/GD-S00013。FS石门中学。震惊:两个编号如此......
  • 2022-11-07 Acwing每日一题
    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我......
  • python 虚拟机中的一般表达式-简单内建对象的创建
    对于一下代码i=1s='python'd={}l=[]解析编译后的pyc文件得到如下结果:从字节码查看consts名字空间与names名字空间,得到以下结果:在Python程序运行开始前,运......
  • zzszoi20221107
    20221107zzszoi模拟赛记录作者zzafanti(FreshOrange)请勿转载这次比赛题目较简单但是思维难度高一点开题顺序\(A-C-B-D\)或\(C-A-D-B\)等等都可大概就是\(A,C\)......
  • 2022强网拟态-only
    2022强网拟态only比赛的时候没做得出来,赛后复现一下。只有一次doublefree的机会,好在用的是seccomp开的沙盒,使得一开始就有很多空闲堆块,里面也残留有libc指针,通过堆风水......
  • P8773 [蓝桥杯 2022 省 A] 选数异或
    题面给定一个长度为\(n\)的数列\(A_{1},A_{2},\cdots,A_{n}\)和一个非负整数\(x\),给定\(m\)次查询,每次询问能否从某个区间\([l,r]\)中选择两个数使得他......
  • 【日总结】2022.11.7
    看了看今天的题,T1给我整自闭了然后就打算光看看题不做了)然后发现除了T4都是洛谷主题库的题,难度黑-黄-蓝-红什么组题鬼才然后发现T2不会做,我现在的实力已经是不会......
  • ICPC2022沈阳站游记
    拿到了本校第一个区域赛银。本来目标只是拿铜的,因为这场队伍实在太多了,但没想到质量不是很高。赛前就决定要拼速度。开赛前看封面,DRXVST1,却没想到这是签到题。还好......
  • Vmware虚拟机突然连接不上网络
    方法一:网络连接状态排查出现该问题,第一步进行网络状态排查,通常也是最有效的方法之一。进入Ctrl+Alt+T打开终端,输入以下命令,查看网络状态信息。sudovim/var/lib/Network......