深入研究源码:Android10

} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {

zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());

} else {

throw new RuntimeException("Unknown command line argument: " + argv[i]);

}

}

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) data[0].effective) | (((long) data[1].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行业感兴趣的新人

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

资料⬅专栏获取

相关推荐
九河云1 小时前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws
Lary_Rock1 小时前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
幺零九零零2 小时前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
热爱跑步的恒川2 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
云飞云共享云桌面3 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
一坨阿亮4 小时前
Linux 使用中的问题
linux·运维
音徽编程5 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
wclass-zhengge6 小时前
Docker篇(Docker Compose)
运维·docker·容器
李启柱7 小时前
项目开发流程规范文档
运维·软件构建·个人开发·设计规范