Android runtime机制(二)zygote进程的启动流程

Android Framework学习三:zygote剖析 zygote 进程启动:Zygote 是 Android 系统中一个重要的进程,是所有 Java 应用程序进程的孵化器 ,它的启动是整个流程的开端。 随后进入app_main.cpp中的main()函数,这是 Zygote 进程在 C++ 层面启动的入口函数。runtime.start () 启动 ZygoteInit:调用runtime.start()函数来启动ZygoteInit。这是 Zygote 进程启动过程中的关键步骤,它会进一步调用一系列函数来完成虚拟机和 JNI 相关的初始化 阅读详情

原文地址:https://blog.youkuaiyun.com/zilx/article/details/72481767

在前一章里介绍了Android runtime的Init进程的启动,在Init进程里,我们知道了runtime环境是如何搭建的和系统属性设置在什么时候设置的,并了解了使用配置文件Init.rc来启动系统Service和其他操作处理。

在这一章里,我们将继续跟进zygote进程的启动过程。在zygote进程启动过程中,虚拟机的创建、jni functions注册及java层ZygoteInit是我们需要关注和理解的,这有助于我们开发更加高效的Android程序。

本文主要以android-7.1.2_r11源码作为参考

主要代码路径: 
\frameworks\base\cmds\app_process\app_main.cpp 
\frameworks\base\core\jni\AndroidRuntime.cpp 
\frameworks\base\include\android_runtime\AndroidRuntime.h 
\libnativehelper\JniInvocation.cpp 
\libnativehelper\include\nativehelper\JniInvocation.h 
\frameworks\base\core\java\android\os\ZygoteInit.java

zygote进程的启动


在《Android runtime机制(一)init进程》篇中我们知道,zygote进程是在Init进程中通过执行如下命令启动的

/system/bin/app_process64//64位系统使用
/system/bin/app_process32//32位系统使用

执行上述命令后,程序执行到了app_main.c的main()函数。

AndroidRuntime


在介绍zygote进程的启动流程之前,我们先来看看两个重要的类AppRuntime 和AndroidRuntime。 
这两个类是Android runtime运行环境的接口类,在Android runtime中起着至关重要的作用。

下面是这两个类之间的关系:

class AppRuntime : public AndroidRuntime

从上面的类继承关系中可以看到,AppRuntime类继承自AndroidRuntime。从后续处理中,在Android 创建运行时环境的时候,主要是通过AppRuntime实例操作。

AndroidRuntime类

AndroidRuntime类是AppRuntime的父类,基本承载着Android runtime的绝大部分操作处理。

下面是AndroidRuntime类的声明,从其声明中,我们可以看到Android runtime的几个重要的接口:

公共接口
  • registerNativeMethods函数。JNI编程时,应用程序向虚拟机注册本地方法时使用。JNI编程时非常重要的一个函数接口。
  • getRuntime函数。提供给外部获取当前进程AndroidRuntime类实例的接口。
  • getJavaVM函数。提供给外部获取当前进程android虚拟机的接口。
  • getJNIEnv函数。提供给外部获取当前进程JNI环境的接口。
私有接口
  • startReg函数。系统级服务的JNI注册函数。
  • startVm函数。创建并启动Android虚拟机。
  • mJavaVM。指向虚拟机的指针,用以访问Android虚拟机。

具体请参考AndroidRuntime类的声明:\frameworks\base\core\jni\AndroidRuntime.h

AppRuntime类

AppRuntime类继承自AndroidRuntime类,重载了AndroidRuntime类的onVmCreated()、onStarted()、onZygoteInit()和onExit()函数,是zygote进程处理时实际runtime入口。

Android runtime类的功能

从上面AppRuntime类和AndroidRuntime类的实现声明中可知,AndroidRumtime主要实现如下功能:

  • 创建并启动虚拟机
  • 注册JNI服务
  • 提供外部访问虚拟机的接口
  • 提供外部访问JNI环境的接口,并提供JNI程序开发的功能支持。

zygote进程的功能处理


zygote进程的入口处理函数是app_main.cpp中的main()函数。Android run time环境的创建和启动,主要是通过AndroidRuntime来实现的。

zygote进程主要处理:

  • app_main.cpp中的main()处理:解析传入参数,实例化AppRuntime,启动Android runtime运行时环境等
  • Android虚拟机的创建
  • 向Android虚拟机注册Android native处理函数
  • java层Zygote初始化处理

下面我们按照程序执行流程来具体梳理一下整个zygote进程的启动处理过程。

app_main.cpp中的main()处理

1. 实例化AndroidRuntime类
///通过执行system/bin/app_process命令,根据service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server传入参数
//argc是传入参数的参数数目:argc=5
//argv是传入的参数值:
//                 argv[0]="/system/bin/app_process64" 
//                 argv[1]="-Xzygote" 
//                 argv[2]="/system/bin"
//                 argv[3]="--zygote"
//                 argv[4]="--start-system-server"
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
2. 解析启动参数
  • 忽略命令行参数:”/system/bin/app_process64”
// Process command line arguments
// ignore argv[0]
//执行此语句块后:
//argc=4
//"/system/bin/app_process64"被忽略,此时argv剩下的值为:
//                 argv[1]="-Xzygote" 
//                 argv[2]="/system/bin"
//                 argv[3]="--zygote"
//                 argv[4]="--start-system-server"
 argc--;
 argv++;
  • 把以“-”打头的参数传递给虚拟机,对于zygote,是把”-Xzygote”传入虚拟机
//执行此语句块后:
//argc=3
//"-Xzygote"被传递给虚拟机,被忽略,此时argv剩下的值为:
//                 argv[2]="/system/bin"
//                 argv[3]="--zygote"
//                 argv[4]="--start-system-server"
int i;
for (i = 0; i < argc; i++) {
//只有第一个参数"-Xzygote"满足,第二个参数是"/system/bin",不是以"-"打头的,所以退出for循环。
     if (argv[i][0] != '-') {
         break;
     }
     if (argv[i][1] == '-' && argv[i][2] == 0) {
         ++i; // Skip --.
         break;
     }
     runtime.addOption(strdup(argv[i]));
 }
  • 解析剩余传入的参数,根据上一个语句块的处理,此时剩余参数值为:”/system/bin”、”–zygote”和”–start-system-server”
// 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++];
        //根据参数"--zygote",表示当前进程是zygote进程,zygote=true,并设置nicename为zygote64(64位)或zygote。
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            //static const char ZYGOTE_NICE_NAME[] = "zygote64";或
            //static const char ZYGOTE_NICE_NAME[] = "zygote";
            niceName = ZYGOTE_NICE_NAME;
        } 
          //根据参数"--start-system-server",需要启动System Server。
          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;
        }
    }
3. 变更zygote进程名为zygote或zygote64
    //niceName在参数解析时被设置。此处变更了app_process启动的进程名为zygote。
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }
4. 调用AndroidRuntime.start()来创建和启动Android 运行时环境
//zygote在参数解析时被设置为true。
//"com.android.internal.os.ZygoteInit"是Android Java运行时环境的初始化类。
//zygote=true。
 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;
    }

Android虚拟机的创建

Android虚拟机的创建是在AndroidRuntime.start()中处理的。 
先初始化JniInvocation,然后通过startVm()->JNI_CreateJavaVM()来创建Android虚拟机。

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
1. JniInvocation

JniInvocation,是一个外部和虚拟机之间的一个中间层,是外部访问虚拟机的API接口,允许外部动态的调用虚拟机内部的实现。其主要实现如下功能:

  • 指定加载的虚拟机。现在Android系统中有两种虚拟机:dalvik和art。现在已基本使用art虚拟机了。
  • 封装虚拟机的对象接口

代码路径: 
\libnativehelper\JniInvocation.cpp 
\libnativehelper\include\nativehelper\JniInvocation.h

JniInvocation的主要接口
//获取默认的虚拟机初始化参数
jint (*JNI_GetDefaultJavaVMInitArgs_)(void*);
//创建虚拟机
jint (*JNI_CreateJavaVM_)(JavaVM**, JNIEnv**, void*);
//获取已创建的虚拟机对象
jint (*JNI_GetCreatedJavaVMs_)(JavaVM**, jsize, jsize*);
虚拟机库的加载

在JniInvocation的Init()函数首先会加载虚拟机库文件。

虚拟机库文件有两种获取方式:

  • 用户指定
  • 系统默认

用户可以通过persist.sys.dalvik.vm.lib.2属性设定虚拟机的库文件,默认的库文件是libart.so。

接口的初始化

在虚拟机库文件加载成功后,需要对JniInvocation的接口进行初始化,提供虚拟机接口功能供外部来访问虚拟机。 
在init()函数里,有如下处理:

//初始化JNI_GetDefaultJavaVMInitArgs_,调用JNI_GetDefaultJavaVMInitArgs_实际上就是调用虚拟机库函数JNI_GetDefaultJavaVMInitArgs。
 if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  //初始化JNI_CreateJavaVM_,调用JNI_CreateJavaVM_实际上就是调用虚拟机库函数JNI_CreateJavaVM。
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  //初始化JNI_GetCreatedJavaVMs_,调用JNI_GetCreatedJavaVMs_实际上就是调用虚拟机库函数JNI_GetCreatedJavaVMs。
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }

函数JNI_CreateJavaVM()、JNI_GetCreatedJavaVMs()、JNI_GetDefaultJavaVMInitArgs()定义在art\runtime\java_vm_ext.cc下,是art虚拟机的内部处理函数。

2. startVm的处理

在JniInvocation初始化之后,虚拟机库文件被加载且接口函数也已被初始化。从JniInvocation的初始化中,我们知道,Android N的默认虚拟机已是ART虚拟机。 
startVm()函数就是用来创建ART虚拟机的。整个的处理过程就是配置虚拟机的属性然后调用虚拟机库函数JNI_CreateJavaVM()来创建。

在虚拟机属性配置过程中,有如下几点值得我们注意:

  • 虚拟机的heapstartsize和heapsize分别被设置为4M和16M。这表明在Java的进程空间中,内存堆栈只有16M的空间
parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
  • 执行模式的配置。执行模式是在属性”dalvik.vm.execution-mode”里配置的
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;
}
  • NativeBridge的配置,在属性”ro.dalvik.vm.native.bridge”里设置。如果没有被设置,则NativeBridge被disabled
// 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);
}

还有其他一些属性配置,具体请参考int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)的实现。

向Android虚拟机注册Android native处理函数

在创建Android虚拟机成功后,Android 运行环境也已准备就绪并运行。在Android系统服务运行的过程中,需要Java层和C/C++层的相互访问。在Android系统中,虚拟机提供JNI机制来实现Java层和C/C++层代码的相互访问。

JNI机制的实现,主要依赖于虚拟机的native method注册机制,使Java类的方法和C/C++函数关联起来。在Java类中调用相应方法的时候能直接寻找到对应的native函数并调用之。

为了相关服务能正常运行,在zygote中就需要对相关服务的JNI功能进行初始化,以使在相关服务运行的时候能够使用底层提供的功能。

此阶段就是来处理系统级的JNI的native函数注册的。用户级别的native函数的注册是通过System.loadLibrary(libraryname)中处理,此部分将在JNI处理中介绍。

下面是AndroidRuntime::start()中的处理,直接调用AndroidRuntime::startReg(env)函数进行注册。

/*
* Register android functions.
*/
if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
}

在AndroidRuntime::startReg(env)函数中,到底是如何注册JNI native functions的呢?注册了哪些JNI native functions呢?我们来看一下该函数的具体处理:

  • 设置Android线程函数。Android所有的线程都是通过函数javaCreateThreadEtc()创建,并attach到虚拟机中
    /*
     * 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);
  • 注册native funcitons。每一个native functions都是通过虚拟机的RegisterNativeMethods()函数接口进行注册的
    /*
     * 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) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

在zygote进程中注册的native functions。请大家参考AndroidRuntime.cpp中的 static const RegJNIRec gRegJNI[]定义,gRegJNI[]是系统级JNI native functions列表。注册native functions详细处理,请参照JNI篇介绍,这里暂时做一个大致介绍:

  • 在虚拟机中查找当前java类是否已经加载,如果已加载,则直接把当前native function 与java类的方法关联。如果当前java类没有加载,则先加载该java类,然后再把native function 与java类的方法关联。
  • 在此注册过程中,我们可以看到,注册中涉及的java类已全部加载到虚拟机中,并与其他进程共享,因为Android java层中,其他的进程都是fork zygote进程的。

java层Zygote初始化处理

在完成虚拟机的创建及JNI native functions的注册后,程序就会执行到Android Java层上。

/*
 * Start VM.  This thread becomes the main thread of the VM, and will
 * not return until the VM exits.
*/
//classname="com.android.internal.os.ZygoteInit"
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 {
    //调用com.android.internal.os.ZygoteInit的main()方法。
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
  }
}    

下面我们来具体梳理一下Zygote Java层的处理过程

1. com.android.internal.os.ZygoteInit类的main()方法

文件目录:\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java。

在ZygoteInit类的main()方法里,主要实现如下功能:

  • 保证在Zygote进程中没有创建线程
  • 创建zygote socket并监听
  • preload Android资源
  • GC初始化并启动
  • 启动System server进程
  • 运行zygote进程的select loop
保证在Zygote进程中没有创建线程

这个处理保证在Zygote Init处理的时候没有线程被创建,也就是说,在Zygote进程中是没有线程存在的。

// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();

同时,在Zygote init处理完成后,关闭保护功能。

ZygoteHooks.stopZygoteNoThreadCreation();
创建zygote socket并监听

zygote socket是应用程序通过Zygote进程来创建应用进程的一个通道,其主要被用在zygote select loop中来进行应用程序进程的创建处理。

//zygote socketName = "ANDROID_SOCKET_zygote"
String socketName = "zygote";
registerZygoteSocket(socketName);
preload Android资源

在zygote init中,Android的相关资源被预加载到Zygote进程空间中。这些资源在后续所有的应用程序进程中都是共享的,因为Android Java层进程都是Zygote的子进程。

//Android资源预加载的入口
preload();

下面是preload()方法的具体实现。

  • preloadClasses:加载class类到虚拟机中,需要加载的类是由/system/etc/preloaded-classes文件指定。它是由相关preloaded-classes文件生成,如: 
    \frameworks\base\preloaded-classes 
    \frameworks\base\compiled-classes-phone 
    虚拟机会通过classloader把preloaded-classes文件中指定的类都加载到虚拟机中,方便应用程序的调用处理。此处会涉及到手机内存空间和手机开机性能问题,手机性能优化方面可以进一步深入研究。
  • preloadResources:加载系统资源
  • preloadOpenGL: 加载显示资源
  • preloadSharedLibraries: 加载共享库,包含android.so、compiler_rt.so和jnigraphics.so
  • preloadTextResources:加载语言库
static void preload() {
   Log.d(TAG, "begin preload");
   Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
   beginIcuCachePinning();
   Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
   Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
   preloadClasses();
   Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
   Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
   preloadResources();
   Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
   Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
   preloadOpenGL();
   Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
   preloadSharedLibraries();
   preloadTextResources();
   // Ask the WebViewFactory to do any initialization that must run in the zygote process,
   // for memory sharing purposes.
   WebViewFactory.prepareWebViewInZygote();
   endIcuCachePinning();
   warmUpJcaProviders();
   Log.d(TAG, "end preload");
}
GC初始化并启动
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
启动System server进程
if (startSystemServer) {
    startSystemServer(abiList, socketName);
}

在startSystemServer()方法里,通过Zygote.forkSystemServer() native函数调用来创建system server 进程。从创建中可以看到,system server进程是zygote进程的子进程。

/* 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,1021,1032,3001,3002,3003,3006,3007,3009,3010",
    "--capabilities=" + capabilities + "," + capabilities,
    "--nice-name=system_server",
    "--runtime-args",
    "com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;

int pid;

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

    /* Request to fork the system server process */
    pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.debugFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
}

在system_server进程创建之后,如果运行的是子进程,即system_server进程,则通过命令执行到com.android.server.SystemServer类的main()方法。

//运行在子进程system_server进程
/* For child process */
if (pid == 0) {
     if (hasSecondZygote(abiList)) {
         waitForSecondaryZygote(socketName);
     }

     //跳转到com.android.server.SystemServer的main()方法继续处理。
     //具体实现请参考handleSystemServerProcess()方法的实现。
     handleSystemServerProcess(parsedArgs);
 }
运行zygote进程的select loop

zygote select loop是在zygote进程中运行,通过zygote socket接受相关命令来创建zygote进程的子进程。

下面是select loop 在main()方法的入口:

Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);

在runSelectLoop()方法中

  • 监听socket,通过Os.poll函数来等待POLLIN事件的到来。
  • 通过ZygoteConnection来读取socket传过来的command并创建进程。
  • zygote进程在运行select loop后,zygote进程就进入无限循环,一直等待socket的command,并做处理。
  //zygote进程在此进入无限循环
  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 {
        //zygote进程被阻塞,直至以下条件达到时退出:
        //a file descriptor becomes ready;
        //the call is interrupted by a signal handler; or
        //the timeout expires.
        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 {
            //调用ZygoteConnection的runOnce()方法来fork进程。
            boolean done = peers.get(i).runOnce();
            if (done) {
                peers.remove(i);
                fds.remove(i);
            }
        }
    }
}

至此,zygote进程启动处理完成,最后一直停留在select loop中运行。

总结及编程相关事项


上面是Zygote进程的启动过程。从Zygote进程的启动过程中,我们可以获取以下知识点,能在我们的编程中给予一定的帮助。

  • 每个虚拟机的内存堆栈只有16M,所以在Java处理中要特别注意内存的管理和使用。
  • JNI的native function注册。如果想让自己的JNI处理在虚拟机中供其他进程调用,则可以把注册函数添加到gRegJNI[]数组里。但是这样会增加系统的开机时间及内存的开销。
  • 虚拟机的属性配置大部分都是依据property属性的值,所以在系统级的优化方面可以根据自己的需求来修改配置虚拟机的属性,从而生成一个适合自己项目的虚拟机。
  • 在Java层的ZygoteInit类中类及资源的加载,会占用大量的开机时间和内存开销,在开机时间优化及系统内存优化方面可以做进一步研究。
  • Java进程都是Zygote进程的子进程,这个是Java进程的一个基本概念,有助于程序开发中性能及内存优化等方案的讨论。
  • zygote进程的启动有许多好的编程技法和算法,如参数的解析、native function的注册、JniInvocation的接口定义和实现、socket的处理、通过命令来执行特定类的方法等,值得借鉴和参考。

Android系统启动流程深度解析:从Zygote到Launcher的进程孵化与调度 本文深度解析Android系统启动流程,从Zygote进程的孵化机制到Launcher的最终呈现。详细探讨了Zygote的预加载和Copy-on-Write技术如何提升应用启动效率,以及SystemServer如何管理系统服务。通过源码分析,揭示Android系统从内核启动到用户界面展示的全过程,为开发者优化系统性能提供实践指导。 阅读详情

相关推荐

Android进程注入实战:从ptrace基础到Zygote系统级控制

进程注入是操作系统层面的核心技术,它允许一个进程动态地将代码加载到另一个进程的地址空间中执行。其原理主要基于系统调用和内存管理机制,通过修改目标进程的执行流或内存映射来实现代码植入。这项技术的核心价值在于无需修改目标程序源码即可实现深度监控、行为分析和功能扩展,广泛应用于安全研究、性能调试和动态分析等领域。在Android生态中,ptrace作为Linux内核提供的进程跟踪接口,是实现进程注入的底层基础,而Zygote作为所有应用进程的孵化器,则提供了系统级注入的可能。本文将以ptrace和Zygote为切

weixin_30387799的博客 318

Android Zygote

1.Zygote Zygote译为“受精卵”,是Android中SystemServer和几乎所有Java应用的孵化器。SystemServer和Java应用的父进程都是zygote。zygote是一个很重要的服务进程,没有zygote就没有Android,Android的启动也离不开zygote。 zygote的启动: zygote是服务进程的别名,zygote是由rc文件定义init启动的服务。从rc文件中可以看出: ①zygote的进程优先级是最高的,priority被设成-20,主要是.

zenmela2011的专栏 9680

Android Zygote启动过程

本文解析 Android Zygote 进程的预加载与 fork 孵化机制,详述从 init 到 app_process 再到 ZygoteInit.main() 的完整启动流程。深入剖析 preloadClasses 加载 5000+ 类的优化原理、COW 写时拷贝节省内存的核心设计、Socket 通信链路及 SystemServer 诞生过程,并提供 ROM 定制预加载实战与常见踩坑经验。

weixin_44081096的博客 644

安卓Zygote详解

一、Zygote, 意为“受精卵”,Android系统中几乎所有的应用进程都是由Zygote进程孵化出来的,Java环境也是由Zygote创建起来的,它建立了我们app运行所需要的环境,是app的祖先,因此,分析它的启动以及内部逻辑显得非常有必要。 *Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接

Leonban的博客 7366

Android NativeBridge过程分析

Art的NativeBridge使用hodini作为callback实际去加载类库 其中做了少量的一些操作 1 Zoygote fork应用进程的时候 frameworks/base/core/jni/com_android_internal_os_Zygote.cpp ForkAndSpecializeCommon函数 bool use_native_bridge = !is_system_server && (instructionSet != NULL) &&

woai110120130的专栏 888

NbInjection:通过替换系统本机网桥支持来注入合子过程的PoC

Nb注入 这是一个替换系统属性“ ro.dalvik.vm.native.bridge”以注入合子进程的示例。 我已经在我的Google Pixel 3(Android 10,Magisk 20.4)上对其进行了测试,它似乎运行良好; 但是它可能不兼容所有设备,如果要使用它,请根据您的设备修改代码。 关于它的工作原理,您可以参考这篇中文。 建造 从Android Studio或命令行运行gradle task :module:assembleMagiskRelease ,magisk模块的zip文件将保存到module / build / outputs / magisk /中。 讨论 执照 麻省理工学院执照

Android Runtime Zygote进程启动与ART初始化原理(8)

Zygote进程是Android系统中的一个特殊进程,它是所有应用进程的父进程。在Android系统启动过程中,Zygote进程率先被创建并初始化,之后每当系统需要创建一个新的应用进程时,都会通过复制Zygote进程来实现,这种机制极大地提高了应用启动速度。

Android开发领域创作者 849

告别时钟树平衡噩梦:在Innovus中巧妙设置stop/ignore pin来优化分段时钟网络

本文深入探讨了在Innovus工具中利用stop/ignore pin优化分段时钟树网络的高阶技巧。针对数字IC后端设计中的时钟树平衡难题,详细解析了特殊引脚属性的战略应用场景和配置方法,帮助工程师有效解决SoC设计中复杂的时钟结构问题,显著提升时序收敛效率。

weixin_30836759的博客 286

Android Zygote启动流程:从init进程到应用孵化的核心机制解析

在Android系统架构中,进程创建机制是系统性能优化的关键环节。其核心原理基于Linux的fork系统调用与写时复制技术,通过共享预加载的公共资源实现高效进程孵化。这一机制的技术价值在于显著提升应用启动速度并降低内存占用,为移动设备的多任务处理提供了基础支撑。在Android平台的具体实现中,Zygote进程作为应用孵化器,通过Socket通信接收启动请求,并利用预加载的类与资源快速创建应用进程。本文聚焦Zygote的启动流程,深入解析从init进程解析rc脚本、app_process搭建Native到J

weixin_33906657的博客 453

紫光PG2L100H平台DDR3 IP核调试实战:从AXI接口到状态机设计的避坑指南

本文详细介绍了在紫光PG2L100H FPGA平台上调试DDR3 IP核的实战经验,重点解析了AXI接口的特殊行为和状态机设计的关键技巧。通过具体代码示例和调试方法,帮助开发者规避常见陷阱,实现高性能DDR3控制器设计,达到1.2GB/s的稳定带宽。

weixin_28717969的博客 218

史上最全的Logisim运算器实验教程(基于华中科技大学计算机组成原理实验)

本博客是实现了Logisim的运算器设计,有具体的运算器设计的思路和运算器设计的电路,适合一步一步的按照思路做。

qq_62325622的博客 4万+

android6.0源码分析之Zygote进程分析

本文将分析Zygote的初始化,以及它负责的进程fork的流程

yangzhihuiguming的专栏 2763

一文搞懂蚁群算法Ant Colony Optimization(ACO)!!!(灵感起源+数学原理+代码实现+实战应用)

本文系统介绍了蚁群算法的原理与实现。首先从蚂蚁觅食行为出发,阐释了信息素正反馈机制如何引导群体找到最短路径。随后详细解析了算法的数学模型,包括状态转移规则和信息素更新机制。通过MATLAB代码演示了算法在旅行商问题(TSP)中的应用,展示了路径构建和优化的完整流程。最后讨论了算法的优势、局限性和实际应用场景。蚁群算法通过模拟生物智能,为解决复杂优化问题提供了一种高效方法,其核心在于信息素的正反馈机制与随机探索的平衡。

qq_42212808的博客 887

Android framework源码分析二 应用进程启动流程源码分析(Android8.0)

点击桌面图标如何启动的app概述1:APP启动的入口Launcher的分析 概述 上一篇文章中对Activity的启动流程做了详细的分析,在第三部分的Step13中ActivityStackSupervisor类的startSpecificActivityLocked方法中分析到如果activity所在进程已经启动的情况,今天就来分析一下进程未启动的情况,即App的启动流程。 其实app的启动最...

马彦虎的博客 5338

Python爬虫实战:模拟登录B站 – 处理Cookie和加密参数

由于B站在登录过程中采用了多种安全措施,包括加密的请求参数和cookie验证,模拟登录成为一项具有挑战性的任务。首先,我们需要获取B站的登录页面,并解析出其中的CSRF令牌和其他隐藏的字段。B站的登录接口通常会包含一些动态的加密参数,我们需要在登录前通过GET请求获取这些信息。本文详细介绍了如何使用Python模拟登录B站,解决加密参数的处理、图形验证码的识别以及登录后的数据抓取。库中的加密方法加密登录请求中的密码。一旦登录成功,我们可以通过维护会话状态,抓取登录后的数据,如个人主页、评论、观看记录等。

2201_76125261的博客 1308

主成分分析(PCA)简洁高效MATLAB实现详解

本文介绍了一个简洁高效的PCA算法实现。该实现通过SVD分解计算主成分,避免了显式协方差矩阵计算,支持两种降维方式:固定维度或按能量比例自动选择。核心步骤包括数据中心化、SVD分解和维度选择,代码量少但功能完整,适用于数据预处理、降维和特征提取等任务。实现中考虑了稀疏矩阵转换、默认参数处理等细节,可直接应用于MATLAB环境。

m0_62153576的博客 63

Zygote的启动流程

preload()方法主要预先加载了framework中通用的类和资源(core/res/res/values/arrays.xml)、openGL、本地共享库、webView的一些资源。在zygote进程对应的文件是app_main.cpp文件,在app_main.cpp文件的main()方法中先解析了init.rc中配置的参数并根据配置的参数设置zygote的状态。startVM()方法多了大量的命令参数拼接最后通过JNI_CreateJavaVM()方法创建虚拟机。

辉色空间 1136

AD(Altium Designer)器件封装——立创商城导出原理图和PCB完成器件封装操作指南

官网:www.SZLCSC.COM以芯片为例器件类——>芯片类——>对应芯片确定芯片——>数据手册1:原理图2:PCB3:打开操作流程选中原理图——>文件——>导出——>AD1: ✔2:导出AD文件操作流程选中PCB图——>文件——>导出——>AD1: ✔2:导出AD文件1:PCB图2:原理图操作流程文件——>打开操作流程选中文件——>打开操作流程项目文件——>添加新的...到工程——>Schematic Library新原理图库操作流程项目文件——>添加新的...到工程——>PCB Library新的PC

XU157303764的博客 5434

深入解析Android Zygote启动流程:从进程孵化到系统优化的核心机制

在Android系统架构中,进程管理是系统性能与稳定性的基石。其核心原理基于Linux的fork机制与写时复制(Copy-On-Write)技术,通过共享内存页实现资源的快速复用。这一机制的技术价值在于显著提升应用启动速度并优化内存使用效率,广泛应用于系统服务启动与应用程序孵化场景。本文聚焦于Android系统的Zygote进程,详细剖析其作为进程孵化器的启动流程,涵盖从init.rc脚本解析、Socket通信建立到预加载(Preload)机制与system_server启动等关键环节,并探讨了USAP(应

weixin_34195142的博客 440

合肥工业大学操作系统实验9

依据操作系统课程所介绍的页面置换算法与动态内存分配的原理,本实验的目的是掌握OPT、FIFO、LRU、LFU、Clock等页面置换算法;掌握可用空间表及分配方法;掌握边界标识法以及伙伴系统的内存分配方法和回收方法。从而深入理解操作系统的内存管理。从而加深对教材上页面置换算法与动态内存分配的理解。

Martin-share的博客 1094

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

YCBlogs:Android App 启动全流程梳理——从 Zygote 孵化到 SystemServer 服务启动的源码级解析

本文围绕 YCBlogs 仓库中 [android/01.基础组件/00.App启动流程梳理.md](https://link.gitcode.com/i/3f9384b218156db410aec28778bf0e43) 的核心内容展开,系统梳理 Android 系统从开机到应用进程诞生的完整链条:init 进程如何拉起 Zygote、Zygote 如何预加载资源并 fork 出 SystemS

gitblog_00494的博客 421

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Android源码阅读---zygote(app_process)进程

Android源码阅读—zygote(app_process)进程 文章目录Android源码阅读---zygote(app_process)进程1. app_processpe的启动2. main函数流程3. 创建java运行环境4. ZygoteInit类主函数4.1 registerZygoteSocket4.2 preload4.3 startSystemServer4.3 runSele...

helloWen 2266

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android应用程序进程启动源码解析

在前面我们从源码层面分析了Android系统启动流程,了解它们也主要是为了我们开发App服务的。应用程序想要启动首先需要应用程序进程存在,而应用程序进程的创建需要SystemServer进程中的ActivityManagerService向Zygote进程发送消息,通过zygote进程fork自身来创建应用程序进程,新创建的应用程序进程就有zygote进程创建的虚拟机实例,同时创建了Binder线程池和Handler消息循环机制,便于进程间消息通信。今天就来从源码角度分析我们关心的Android应用程序进.

周将的博客 873

Android 面试必备 - 系统、App、Activity 启动过程

前言 最近准备更新 Android 面试必备基础知识系列,有兴趣的可以关注我的微信公众号 stormjun94,有更新时,第一时间会在微信公众号上面发布,同时,也会同步在 GitHub 上面更新,如果觉得对你有所帮助的话,请帮忙 star。 Android 面试必备 - http 与 https 协议 Android 面试必备 - 计算机网络基本知识(TCP,UDP,Http,https) And...

徐公,微信公众号同名 3963

Android系统启动,用过安卓手机的都知道,你还不知道吗?

Android系统启动一.Android系统启动概述1.启动电源以及系统启动2.引导程序BootLoader3.Linux内核启动4.init进程启动5.Zygote进程启动6.SystemServer进程启动7.AMS启动Launcher进程二.Android系统启动详解1.init进程的启动过程init进程的main函数(init.cpp)执行过程:2.Zygote进程的启动过程(C层)app...

LeeDuoZuiShuai的博客 2455
上一篇: Android runtime机制(一)init进程
下一篇: Android 使用split函数进行多个空格分割
dodod2012
博客等级 码龄15年 244粉丝 98原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值