深入研究源码:Android10

} else if (argvi.startsWith(SOCKET_NAME_ARG)) {

zygoteSocketName = argvi.substring(SOCKET_NAME_ARG.length());

} else {

throw new RuntimeException("Unknown command line argument: " + argvi);

}

}

final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);//根据socketName判断是否是primaryZygote,可能还有secondZygote

if (abiList == null) { //如果支持架构为空,直接抛出异常

throw new RuntimeException("No ABI list supplied.");

}

// In some configurations, we avoid preloading resources and classes eagerly.

// In such cases, we will preload things prior to our first fork.

if (!enableLazyPreload) {

bootTimingsTraceLog.traceBegin("ZygotePreload");

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

SystemClock.uptimeMillis());

preload(bootTimingsTraceLog);

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

SystemClock.uptimeMillis());

bootTimingsTraceLog.traceEnd(); // ZygotePreload

} else {

Zygote.resetNicePriority();

}

// Do an initial gc to clean up after startup

bootTimingsTraceLog.traceBegin("PostZygoteInitGC");

gcAndFinalize(); //调用ZygoteHooks.gcAndFinalize()进行垃圾回收

bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

bootTimingsTraceLog.traceEnd(); // ZygoteInit

// Disable tracing so that forked processes do not inherit stale tracing tags from

// Zygote.

Trace.setTracingEnabled(false, 0);

Zygote.initNativeState(isPrimaryZygote);//jni调用初始化zygote的状态,是否为isPrimaryZygote

ZygoteHooks.stopZygoteNoThreadCreation(); //结束zygote创建,其实内部是调用runtimezygote_no_threads_赋值为false,为创建本地线程做准备

zygoteServer = new ZygoteServer(isPrimaryZygote); //创建zygoteServer,为其他进程初始化创建时与zygote通信做准备

if (startSystemServer) { //判断是否需要startSystemServer

Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//通过fork的方式开启zygote的子进程,systemServer,并返回一个Runnale对象

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the

// child (system_server) process.

if (r != null) {//如果是zygote进程,则r==null,如果不是zygote进程,也就是systemServer进程,则执行下面的代码

r.run();

return;

}

}

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

// The select loop returns early in the child process after a fork and

// loops forever in the zygote.

caller = zygoteServer.runSelectLoop(abiList); //zygote进程进入死循环中,来获取子进程发送的消息

} catch (Throwable ex) {

Log.e(TAG, "System zygote died with exception", ex);

throw ex;

} finally {

if (zygoteServer != null) {

zygoteServer.closeServerSocket(); //如果发生异常,则说明zygote初始化失败,zygoteServer也需要关闭

}

}

// We're in the child process and have exited the select loop. Proceed to execute the

// command.

if (caller != null) {

caller.run();

}

}

zygote的大概流程我们已经梳理完了,现在我们来总结一下

  1. 解析对应的zyogte.rc脚本
  2. 调用app_process/appMain.cpp
  3. 设置进程名为zygote
  4. 调用zygoteInit.java初始化zygote进程
  5. JNI调用zygoteInit.cpp完成进程创建
  6. 调用runSelectionLoop(),接收其他进程发送的消息创建子进程

Zygote是如何fork出SystemServer的

我们都知道,Android系统中,zyogte进程是Java世界的首个进程(init进程为头号进程),是直接通过exec的系统调用创建的,其他的进程,包括system_server,都是zygote进程的子进程,那我们接下来从源码的角度来看一下,zygote是如何forksystem_server

public static void main(String argv\[\]) {

...

if (startSystemServer) {

Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the

// child (system_server) process.

if (r != null) { //如果r不为空,说明是system_server进程

r.run(); //调用其run方法

return;

}

}

...

}

...

}

由上面的分析我们看到,根据zygote.rc的参数,解析出是否需要startSystemServer,如果为true,则调用forkSystemServer来fork出子进程SystemServer,并且执行其返回的Runnable的run()方法,我们先来看看forkSystemServer具体做了什么

/**

  • Prepare the arguments and forks for the system server process.
  • 为forkSystemServer进程准备参数,并且创建system server进程
  • @return A {@code Runnable} that provides an entrypoint into system_server code in the child
  • process; {@code null} in the parent.
    /
    private static Runnable forkSystemServer(String abiList, String socketName,
    ZygoteServer zygoteServer) {
    //Linux使用POSIX capabilities代替传统的信任状模型
    long capabilities = posixCapabilitiesAsBits( //设置进程权能
    OsConstants.CAP_IPC_LOCK, //允许锁定共享内存片段
    OsConstants.CAP_KILL, //允许对不属于自己的进程发送信号
    OsConstants.CAP_NET_ADMIN, // 允许执行网络管理任务:接口、防火墙和路由等
    OsConstants.CAP_NET_BIND_SERVICE, //允许绑定到小于1024的端口
    OsConstants.CAP_NET_BROADCAST, //允许网络广播和多播访问
    OsConstants.CAP_NET_RAW, //允许网络广播和多播访问
    OsConstants.CAP_SYS_MODULE, //插入和删除内核模块
    OsConstants.CAP_SYS_NICE, //允许提升优先级,设置其它进程的优先级
    OsConstants.CAP_SYS_PTRACE, //允许配置进程记帐
    OsConstants.CAP_SYS_TIME, //允许改变系统时钟
    OsConstants.CAP_SYS_TTY_CONFIG, //允许配置TTY设备
    OsConstants.CAP_WAKE_ALARM,
    OsConstants.CAP_BLOCK_SUSPEND
    );
    /
    Containers run without some capabilities, so drop any caps that are not available. */
    StructCapUserHeader header = new StructCapUserHeader(
    OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
    StructCapUserData\[\] data; //用户权能数据
    try {
    data = Os.capget(header); //获取进程权能,存储到data中
    } catch (ErrnoException ex) {
    throw new RuntimeException("Failed to capget()", ex);
    }
    capabilities &= ((long) data0.effective) | (((long) data1.effective) << 32);

/* Hardcoded command line to start the system server */

/使用硬编码的方式定义出启动system server的参数字符串args /

String args\[\] = {

"--setuid=1000", //用户id

"--setgid=1000",//用户组id

"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"

  • "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
    "--capabilities=" + capabilities + "," + capabilities, //进程权能
    "--nice-name=system_server", //进程niceName
    "--runtime-args",
    "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    "com.android.server.SystemServer",
    };
    ZygoteArguments parsedArgs = null;

int pid; //processId,进程id

try {

parsedArgs = new ZygoteArguments(args); 创建ZygoteArguments对象,把args解析为需要的参数

Zygote.applyDebuggerSystemProperty(parsedArgs);

Zygote.applyInvokeWithSystemProperty(parsedArgs);

boolean profileSystemServer = SystemProperties.getBoolean(

"dalvik.vm.profilesystemserver", false); //跟Art虚拟机相关,暂时不做深究

if (profileSystemServer) {

parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;

}

/* Request to fork the system server process */

pid = Zygote.forkSystemServer( //fork创建SystemServer

parsedArgs.mUid, parsedArgs.mGid,

parsedArgs.mGids,

parsedArgs.mRuntimeFlags,

null,

parsedArgs.mPermittedCapabilities,

parsedArgs.mEffectiveCapabilities);

} catch (IllegalArgumentException ex) {

throw new RuntimeException(ex);

}

/* For child process */

if (pid == 0) { //pid为0,则说明是zygote进程,进行最后的收尾工作

if (hasSecondZygote(abiList)) {

waitForSecondaryZygote(socketName);

}

zygoteServer.closeServerSocket();

return handleSystemServerProcess(parsedArgs);

}

return null;

}

代码最后调用了Zygote.forkSystemServer()来创建SystemServer,我们接着来跟一下

public static int forkSystemServer(int uid, int gid, int\[\] gids, int runtimeFlags,

int\[\]\[\] rlimits, long permittedCapabilities, long effectiveCapabilities) {

ZygoteHooks.preFork();//内部调用ART的Runtime对zygote的线程池的线程进行清理

// Resets nice priority for zygote process.

resetNicePriority();

int pid = nativeForkSystemServer( //JNI调用,真正创建systemServer进程的函数

uid, gid, gids, runtimeFlags, rlimits,

permittedCapabilities, effectiveCapabilities);

// Enable tracing as soon as we enter the system_server.

if (pid == 0) {

Trace.setTracingEnabled(true, runtimeFlags);

}

ZygoteHooks.postForkCommon();

return pid;

}

接着跟下去,到c++的本地代码中 zygote.cpp

static jint com_android_internal_os_Zygote_nativeForkSystemServer(

JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,

jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,

jlong effective_capabilities) {

...

pid_t pid = ForkCommon(env, true,

fds_to_close,

fds_to_ignore);//从zygote进程fork出子进程,并返回processId

...

return pid;

}

到这里我们就把相关源码分析完了,我们来总结下:

  1. 解析zygote.rc的相关脚本,获取startSystemserver的属性字段
  2. 调用startSystemServer()
  3. 调用forkSystemServer(),为当前进程赋予权限,并设置UID,GID
  4. 创建ZygoteArgument,调用zygote.forkSystemServer
  5. JNI调用native的函数,nativeForkSystemServer完成进程的fork工作

普通进程(UASP--unspecialized app process),是通过什么方式被fork出来的

这里我们只分析zygote相关的源码,完整流程等分析AMS时一起总结

zygoteInit中,最后调用了zyogteServer的runSelectionLoop()函数,进入一个无限循环中,我们来看下代码

Runnable runSelectLoop(String abiList) { //此处使用了selcet IO复用机制,这个我们以后专门来分析Linux的IO复用机制

...

while (--pollIndex >= 0) {

...

if (pollIndex == 0) {

// Zygote server socket

ZygoteConnection newPeer = acceptCommandPeer(abiList);//创建socket连接的服务端

peers.add(newPeer);

socketFDs.add(newPeer.getFileDescriptor());

} else if (pollIndex < usapPoolEventFDIndex) {

// Session socket accepted from the Zygote server socket

try {

ZygoteConnection connection = peers.get(pollIndex); //获取到客户端连接对象ZygoteConnection

final Runnable command = connection.processOneCommand(this); //读取一个sokcet命令,并fork出子进程,执行子进程的main函数

// TODO (chriswailes): Is this extra check necessary?

if (mIsForkChild) {

// We're in the child. We should always have a command to run at this

// stage if processOneCommand hasn't called "exec".

if (command == null) {

throw new IllegalStateException("command == null");

}

return command;

} else {

// We're in the server - we should never have any commands to run.

if (command != null) {

throw new IllegalStateException("command != null");

}

// We don't know whether the remote side of the socket was closed or

// not until we attempt to read from it from processOneCommand. This

// shows up as a regular POLLIN event in our regular processing loop.

if (connection.isClosedByPeer()) {

connection.closeSocket();

peers.remove(pollIndex);

socketFDs.remove(pollIndex);

}

}

}

...

}

...

}

}

这里当pollIndex==0先调用acceptCommandPeer()创建sokcet连接的服务端,其他条件下,调用acceptCommandPeer()获取一个ZygoteConnect对象,并执行其processOneCommand()函数,读取一个sokcet命令,并fork出子进程,执行子进程的main函数,我们还是接着跟一下这个函数

Runnable processOneCommand(ZygoteServer zygoteServer) {

String args\[\];

ZygoteArguments parsedArgs = null;

FileDescriptor\[\] descriptors;

try {

args = Zygote.readArgumentList(mSocketReader); //从sokcet中读取参数

// TODO (chriswailes): Remove this and add an assert.

descriptors = mSocket.getAncillaryFileDescriptors(); //获取其附带的文件描述符

} catch (IOException ex) {

throw new IllegalStateException("IOException on command socket", ex);

}

...

int pid = -1;

FileDescriptor childPipeFd = null;//子进程,使用管道进行进程间通信,

FileDescriptor serverPipeFd = null;

parsedArgs = new ZygoteArguments(args); //创建Zygote参数对象

...

pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,

parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,

parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,

parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);

//Forks a new VM instance

//创建一个新的VM实例对象,也就是我们平时说的沙盒隔离机制(sandbox)

try {

if (pid == 0) {

// in child

zygoteServer.setForkChild();//设置标志位mIsForkChild为true

...

return handleChildProc(parsedArgs, descriptors, childPipeFd,

parsedArgs.mStartChildZygote); //处理子进程的创建

} else {

// In the parent. A pid < 0 indicates a failure and will be handled in

// handleParentProc.

IoUtils.closeQuietly(childPipeFd);

childPipeFd = null;

handleParentProc(pid, descriptors, serverPipeFd);//如果pid>0,则为子进程设置进程号,否则就是创建失败

return null;

}

} finally {

IoUtils.closeQuietly(childPipeFd);

IoUtils.closeQuietly(serverPipeFd);

}

}

这里根据传递过来的参数创建zygoteArgs对象,并创建出VM虚拟机对象,最终调用handleChildProc()来创建子进程,继续跟踪代码

private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor\[\] descriptors,

FileDescriptor pipeFd, boolean isZygote) {

...

if (parsedArgs.mNiceName != null) { //判断mNiceName不为空

Process.setArgV0(parsedArgs.mNiceName); //设置mNiceName为进程名

}

// End of the postFork event.

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

if (parsedArgs.mInvokeWith != null) { //判断参数中mInvokeWith为空时,使用exec的系统调用开启进程

...

} else {

if (!isZygote) { //非zygote模式

return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,

parsedArgs.mRemainingArgs, null /* classLoader /);
} else { //zygote模式
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /
classLoader */); //zygoteInit的备选函数,同时初始化Zygote进程

}

}

}

此处我们只关心由Zyogte进程fork出子进程的情况,跟踪zygoteInit()这个函数

public static final Runnable zygoteInit(int targetSdkVersion, String\[\] argv,

ClassLoader classLoader) {

...

RuntimeInit.commonInit(); //对runtime进行初始化

ZygoteInit.nativeZygoteInit(); //JNI调用,nativeZygoteInit

return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//找到Appde 主函数并初始化调用

}

这里首先的对Runtime进行初始化,然后通过JNI对zygote进行真正的初始化操作,函数代码如下

static AndroidRuntime* gCurRuntime = NULL;

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)

{

gCurRuntime->onZygoteInit(); //调用AndroidRuntime的zygoteInit

}

这里是调用了AndroidRuntimeonZygoteInit(),此处点进去可以看到它是一个虚函数,那么应该是由的子类对象来做的具体实现,之前我们也分析过,AndroidRuntimeapp_processapp_main中又一个子类对象AppRuntime,我们来看一下

public:

AppRuntime(char* argBlockStart, const size_t argBlockLength)

: AndroidRuntime(argBlockStart, argBlockLength)

, mClass(NULL)

{

}

...

virtual void onZygoteInit()

{

sp proc = ProcessState::self();

ALOGV("App process: starting thread pool.\n");

proc->startThreadPool();//开启Bind线程池线程,设置线程名称

}

...

};

此处创建了一个ProcessState的对象,并调用了它的startThreadPool()函数,跟踪下去可以发现内部调用了spawnPooledThread的函数来创建线程并启动的

void ProcessState::spawnPooledThread(bool isMain)

{

if (mThreadPoolStarted) { //判断线程已开启

String8 name = makeBinderThreadName(); //创建Binder线程池名称

ALOGV("Spawning new pooled thread, name=%s\n", name.string());

sp t = new PoolThread(isMain); //创建主线程

t->run(name.string()); //执行线程

}

}

handleChildProc()这一系列代码执行完毕后,会调用handleParentProc()对子进程创建状态进行判断,如果pid>0则说明创建成功,到此处我们子进程以及其相关线程就准备完毕了

现在来总结下

  1. 调用runSelectLoop,循环读取消息
  2. 调用acceptCommandPeer创建Sokcet服务端的连接对象ZygoteConnection
  3. 调用acceptOneCommand读取Soket的消息
  4. 解析参数,并创建虚拟机实例对象
  5. 调用handleChildProcess处理子进程的创建
  6. 调用zygoteInit.zyogteInit(args...)把参数传递进去
  7. 调用native方法,进行最终的初始化
  8. 回调到app_process/app_main.cppAppRuntime具体实现中
  9. 开启Binder线程池,完成子进程创建

额外加餐

ZygoteServer源码

上面我们分析Zygote流程时涉及到一个类,ZygoteServer,下面我们来具体看下,它是如何创建的

在zygote的main函数中是这么初始化的

zygoteServer = new ZygoteServer(isPrimaryZygote);

那我们就从这个构造函数入手

/**

  • Initialize the Zygote server with the Zygote server socket, USAP pool server socket, and USAP
  • pool event FD.
  • @param isPrimaryZygote If this is the primary Zygote or not.
    */
    ZygoteServer(boolean isPrimaryZygote) {
    mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

if (isPrimaryZygote) { //根据zygote.rc中的参数判断是否是PrimaryZygote

mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);//把PRIMARY_SOCKET_NAME赋值给mZygoteSocket

mUsapPoolSocket =

Zygote.createManagedSocketFromInitSocket(

Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);//把USAP_POOL_PRIMARY_SOCKET_NAME赋值给mUsapPoolSocket

} else {

mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);//把SECONDARY_SOCKET_NAME赋值给mZygoteSocket

mUsapPoolSocket =

Zygote.createManagedSocketFromInitSocket(

Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);//把USAP_POOL_SECONDARY_SOCKET_NAME赋值给mUsapPoolSocket

}

fetchUsapPoolPolicyProps();

mUsapPoolSupported = true;

}

上面的代码里主要是把zygote.rc中的配置取出来,其中涉及到了两个socket,mZygoteSocketmUsapPoolSocket;也涉及到两个Zygote,PrimaryZygoteSecondZygote

但是你可能会奇怪,咱们的zygote.rc中,怎么没有这个东西呢?我再把这个文件贴一遍

WORKING_DIRECTORY/out/target/product/generic_x86/root/init.zygote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

class main

priority -20

user root

group root readproc reserved_disk

socket zygote stream 660 root system

socket usap_pool_primary stream 660 root system

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart audioserver

onrestart restart cameraserver

onrestart restart media

onrestart restart netd

onrestart restart wificond

writepid /dev/cpuset/foreground/tasks

唯一跟primary有关的,是socket usap_pool_primary stream 660 root system,那SecondZygote去哪了呢?

这个跟咱们编译的版本是有关系的,当前编译的版本中,只支持32为的应用,所以只有32位的PrimaryZygote,那咱们来看一下我根据源码编译的Pixel 2的Android10系统中有没有

使用adb shell 查看

cat init.zygote64_32.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

class main

priority -20

user root

group root readproc reserved_disk

socket zygote stream 660 root system

socket usap_pool_primary stream 660 root system

onrestart write /sys/android_power/request_state wake

onrestart write /sys/power/state on

onrestart restart audioserver

onrestart restart cameraserver

onrestart restart media

onrestart restart netd

onrestart restart wificond

writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload

class main

priority -20

user root

group root readproc reserved_disk

socket zygote_secondary stream 660 root system

socket usap_pool_secondary stream 660 root system

onrestart restart zygote

writepid /dev/cpuset/foreground/tasks

这里很清楚的看得到,64位的zygote是PrimaryZygote,32位的zygote是SecondZygote,不同的二进制文件可以由不同的Zygote启动,同时兼容64位和32位程序

我们再来看看上面提到的两个Socket是干什么的

/**

  • Listening socket that accepts new server connections.
    */
    private LocalServerSocket mZygoteSocket;

/**

  • The name of the unspecialized app process pool socket to use if the USAP pool is enabled.
    */
    private LocalServerSocket mUsapPoolSocket;

...

ZygoteServer(boolean isPrimaryZygote) {

...

mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);

mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);

...

}

这里两个sokcet的对象的创建都调用的同一个函数createManagedSocketFromInitSocket()

/** Prefix prepended to socket names created by init */

private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

/**

  • Creates a managed LocalServerSocket object using a file descriptor
  • created by an init.rc script. The init scripts that specify the
  • sockets name can be found in system/core/rootdir. The socket is bound
  • to the file system in the /dev/sockets/ directory, and the file
  • descriptor is shared via the ANDROID_SOCKET_ environment
  • variable.
    */
    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
    int fileDesc;
    final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//拼接为socket的全路径名
    try {
    String env = System.getenv(fullSocketName);
    fileDesc = Integer.parseInt(env);
    } catch (RuntimeException ex) {
    throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
    }

try {

FileDescriptor fd = new FileDescriptor();//创建文件描述符

fd.setInt$(fileDesc); //把获取到的fileDesc设置进去

return new LocalServerSocket(fd); //返回该Socket对象

} catch (IOException ex) {

throw new RuntimeException(

"Error building socket from file descriptor: " + fileDesc, ex);

}

}

我们使用adb来查看下,很容易的查看到两个Zygote相关的socketFd

ZygoteHooks相关源码

我们来简单补充一点zygoteHooks的源码分析,分析这个问题的目的在于,理清出Dalvik和ART在Android10源码中的关系

上面的源码分析中,有几个地方调用 ZygoteHooks的相关源码,我们来简单分析下

ZygoteHooks.startZygoteNoThreadCreation() && ZygoteHooks.stopZygoteNoThreadCreation()

我们发现这个ZygoteHooks其实是ART包下的

./art/runtime/native/dalvik_system_ZygoteHooks.cc

static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,

jclass klass ATTRIBUTE_UNUSED) {

Runtime::Current()->SetZygoteNoThreadSection(true);

}

可以看到这个函数是一个JNI的接口,内部调用了RuntimeSetZygoteNoThreadSection函数

./art/runtime/runtime.h

// Whether zygote code is in a section that should not start threads.

bool zygote_no_threads_;

void SetZygoteNoThreadSection(bool val) {

zygote_no_threads_ = val;

}

bool IsZygoteNoThreadSection() const {

return zygote_no_threads_;

}

可以看到这里其实就是设置了一个标志为,源码注释中也说明了,该字段是为了区分处于zygote模式时,不去开启线程,那我们来看看这个zygote_no_threads_的字段哪里使用到了

./art/runtime/runti​ me.cc
:
...

复制代码
zygote_no_threads_(false),   

...   

{   

...

}

这里在Runtime构造初始化时,首先把其设置为false,也就是默认情况下,Runtime是会去开启线程的

再来看看返回zygote_no_threads_IsZygoteNoThreadSection()这个函数在哪里有使用

./art/runtime/native/java_lang_Thread.cc

static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,

jboolean daemon) {

// There are sections in the zygote that forbid thread creation.

Runtime* runtime = Runtime::Current();

if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {//判断是zygote进程,并且IsZygoteNoThreadSection()返回值为true时

jclass internal_error = env->FindClass("java/lang/InternalError");

CHECK(internal_error != nullptr);

env->ThrowNew(internal_error, "Cannot create threads in zygote");//直接抛出异常,

return; //结束当前函数

}

Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);//如果不是zygote进程,才去创建本地线程

}

这里又是一个JNI的接口函数,是用来创建本地线程的(根据类名和方法名也可以猜到),注释中也做了说明,只有不是zygote进程时才会去创建本地线程
stopZygoteNoThreadCreation()函数也是一样,同样是设置标志为,设置为false,那么就可以去创建线程了

写在最后

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

ternalError");

CHECK(internal_error != nullptr);

env->ThrowNew(internal_error, "Cannot create threads in zygote");//直接抛出异常,

return; //结束当前函数

}

Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);//如果不是zygote进程,才去创建本地线程

}

这里又是一个JNI的接口函数,是用来创建本地线程的(根据类名和方法名也可以猜到),注释中也做了说明,只有不是zygote进程时才会去创建本地线程
stopZygoteNoThreadCreation()函数也是一样,同样是设置标志为,设置为false,那么就可以去创建线程了

写在最后

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

外链图片转存中...(img-fHj9tfku-1719112726916)一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

相关推荐
SelectDB18 小时前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
zzzzzz3102 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
大树886 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz6 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
网络研究院6 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展