序言
上一篇Android源码分析挖掘(一) 开天辟地init进程分析了Android系统从按下开机键到init进程启动服务的过程,init进程启动了很多服务,如Zygote,ServiceManager,SurfaceFlinger等,本片分析一下Zygote进程被启动后都干了些啥。
上篇介绍了init进程通过init.rc文件启动了服务,那么Zygote服务是在init.rc哪一条指令被定义的呢,回到源码init.rc文件,路径:system/core/rootdir/init.rc
# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#
import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import /system/etc/init/hw/init.${ro.zygote}.rc
...
可以看到,import /system/etc/init/hw/init.${ro.zygote}.rc,这一行的import的意思就是读取这个路径文件的所有内容,在init进程启动服务时,会一并启动。
在init.rc同目录下就能找到几个对应的文件:init.zygote32_64.rc、``init.zygote32.rc、``init.zygote64_32.rc、``init.zygote64.rc,具体import哪个文件与具体设备硬件有关,这里就以init.zygote64.rc分析,代码内容如下:
service zygote /system/bin/app_process64 -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 exec_background - system system -- /system/bin/vdc volume abort_fuse
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
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
暂时可以只关注第一行,简单点认为,可以认为启动了/system/bin/app_process64这个程序,后面携带了一系列参数,这些参数需要重点关注,因为关系到后续是启动SystemServer还是app:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
那么这个zygote程序源码在哪里呢?可以通过以上启动systemserver参数的字符串全局查找一下,命令如下:
grep "start-system-server" ./ -rn
//搜索结果
./base/cmds/app_process/app_main.cpp:200: // --start-system-server : Start the system server.
./base/cmds/app_process/app_main.cpp:269: } else if (strcmp(arg, "--start-system-server") == 0) {
./base/cmds/app_process/app_main.cpp:310: args.add(String8("start-system-server"));
./base/core/java/com/android/internal/os/ZygoteInit.java:920: if ("start-system-server".equals(argv[i])) {
./base/core/jni/AndroidRuntime.cpp:1195: static const String8 startSystemServer("start-system-server");
可以看到有c++代码,也有java代码,但是由于此时虚拟机环境还没有建立,不可能进入到java代码中,所以源码一定是./base/cmds/app_process/app_main.cpp,查看源码:
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif
int main(int argc, char* const argv[])
{
//打印传入的参数日志
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[i]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
int i;
...
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
String8 niceName;
...
while (i < argc) {
const char* arg = argv[i++];
//如果参数中携带有--zygote,就把zygote置为true,并将nicName赋值为zygoteXX
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
//如果参数中携带有--start-system-server,就把startSystemServer置为true
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else
...
}
Vector<String8> args;
if (!className.isEmpty()) {
...
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
//上面startSystemServer为true,args中加入start-system-server
if (startSystemServer) {
args.add(String8("start-system-server"));
}
...
//系统架构
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
//把剩余参数都添加到Vector容器中
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
//修改进程的名称为zygoteXX
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
//执行AndroidRuntime的start函数,并传入参数com.android.internal.os.ZygoteInit, args,true
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
...
}
整体流程还是很简单的,基本可以概括为:
1.解析参数,检查参数中是否存在--zygote、--start-system-server
2.根据解析出来的内容,重新装填参数
2.将进程名称修改为zygoteXX
3.调用AndroidRuntime.start函数,并传入"com.android.internal.os.ZygoteInit",重新装填的参数和true
通过文件内搜索可知,AppRuntime继承自AndroidRuntime:
class AppRuntime : public AndroidRuntime
{
...
}
故而分析AndroidRuntime代码,通过如下命令搜索:
find -name AndroidRuntime.cpp
//搜索结果
./base/core/jni/AndroidRuntime.cpp
源码如下:
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
//配置环境变量
...
/* start the virtual machine */
JniInvocation jni_invocation;
//加载libart.so
jni_invocation.Init(NULL);
JNIEnv* env;
//启动VM
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
//回调AppRuntime重写的方法
onVmCreated(env);
/*
* Register android functions.
*/
//注册jni函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//将Vector转换为String数组
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
//查找com.android.internal.os.ZygoteInit的class对象
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//查找main方法,参数为String数组
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);
...
}
}
...
}
start主要做了一下几件事:
1.配置系统环境变量
2.加载libart.so库
3.启动虚拟机,注册jni函数
4.启动java类com.android.internal.os.ZygoteInit的main方法,并传入之前的参数
加载libart.so
下面简要分析一下以上流程,环境变量就不说了,看一下jni_invocation.Init(NULL)加载libart.so的流程,由于我通过JniInvocation.cpp没有搜索到内容,所以先通过AndroidRuntime.cpp中导入的头文件来搜索,搜索JniInvocation.h,搜索到源码路径:libnativehelper/include_platform/nativehelper/JniInvocation.h,源码如下:
struct JniInvocationImpl* JniInvocationCreate();
bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library);
class JniInvocation final {
//构造函数
public:
JniInvocation() {
impl_ = JniInvocationCreate();
}
~JniInvocation() {
JniInvocationDestroy(impl_);
}
//这个就是调用的init方法
bool Init(const char* library) {
//调用JniInvocationInit函数,library传入NULL
return JniInvocationInit(impl_, library) != 0;
}
static const char* GetLibrary(const char* library, char* buffer) {
return JniInvocationGetLibrary(library, buffer);
}
private:
JniInvocation(const JniInvocation&) = delete;
JniInvocation& operator=(const JniInvocation&) = delete;
//原来最终是这个cpp文件
JniInvocationImpl* impl_;
};
原来JniInvocation只是一个代理包装类,业务是交给JniInvocationImpl实现的,搜索JniInvocationImpl.cpp文件,结果也没有搜到,嘿,奇了怪了,总不能没有吧,后来使用 grep JniInvocationImpl ./ -rn 来搜索,果然就搜索到了,原来一直在关注.cpp,忽略了linux也可以运行.c的,搜索结果如下:
./JniInvocation.c:35:struct JniInvocationImpl {
./JniInvocation.c:48:static struct JniInvocationImpl g_impl;
./JniInvocation.c:138:struct JniInvocationImpl* JniInvocationCreate() {
./JniInvocation.c:146:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
./JniInvocation.c:199:void JniInvocationDestroy(struct JniInvocationImpl* instance) {
./include_platform/nativehelper/JniInvocation.h:33:struct JniInvocationImpl;
./include_platform/nativehelper/JniInvocation.h:36: * Creates an instance of a JniInvocationImpl.
./include_platform/nativehelper/JniInvocation.h:38:struct JniInvocationImpl* JniInvocationCreate();
./include_platform/nativehelper/JniInvocation.h:41: * Associates a library with a JniInvocationImpl instance. The library should export C symbols for
./include_platform/nativehelper/JniInvocation.h:56:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library);
./include_platform/nativehelper/JniInvocation.h:59: * Release resources associated with JniInvocationImpl instance.
./include_platform/nativehelper/JniInvocation.h:61:void JniInvocationDestroy(struct JniInvocationImpl* instance);
./include_platform/nativehelper/JniInvocation.h:122: JniInvocationImpl* impl_;
./libnativehelper_lazy.c:257:struct JniInvocationImpl* JniInvocationCreate() {
./libnativehelper_lazy.c:258: typedef struct JniInvocationImpl* (*M)();
./libnativehelper_lazy.c:262:void JniInvocationDestroy(struct JniInvocationImpl* instance) {
./libnativehelper_lazy.c:263: typedef void (*M)(struct JniInvocationImpl*);
./libnativehelper_lazy.c:267:bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library) {
./libnativehelper_lazy.c:268: typedef bool (*M)(struct JniInvocationImpl*, const char*);
可以很确定说,源码肯定在./JniInvocation.c中,打开源码文件,查看:
static const char* kDefaultJniInvocationLibrary = "libart.so";
bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
//传入的library_name为NULL
library_name = JniInvocationGetLibrary(library_name, buffer);
//看函数名字应该是调用linux的dlopen函数,用于打开library为命名的so
DlLibrary library = DlOpenLibrary(library_name);
if (library == NULL) {
//如果library为空,library_name不是libart.so
if (strcmp(library_name, kDefaultJniInvocationLibrary) == 0) {
ALOGW("Falling back from %s to %s after dlopen error: %s",
library_name, kDefaultJniInvocationLibrary, DlGetError());
//就加载libart.so
library_name = kDefaultJniInvocationLibrary;
library = DlOpenLibrary(library_name);
//如果加载libart.so失败,就返回
if (library == NULL) {
ALOGE("Failed to dlopen %s: %s", library_name, DlGetError());
return false;
}
}
//查找函数JNI_GetDefaultJavaVMInitArgs
DlSymbol JNI_GetDefaultJavaVMInitArgs_ = FindSymbol(library, "JNI_GetDefaultJavaVMInitArgs");
if (JNI_GetDefaultJavaVMInitArgs_ == NULL) {
return false;
}
//查找函数JNI_CreateJavaVM
DlSymbol JNI_CreateJavaVM_ = FindSymbol(library, "JNI_CreateJavaVM");
if (JNI_CreateJavaVM_ == NULL) {
return false;
}
//查找函数JNI_GetCreatedJavaVMs
DlSymbol JNI_GetCreatedJavaVMs_ = FindSymbol(library, "JNI_GetCreatedJavaVMs");
if (JNI_GetCreatedJavaVMs_ == NULL) {
return false;
}
instance->jni_provider_library_name = library_name;
instance->jni_provider_library = library;
instance->JNI_GetDefaultJavaVMInitArgs = (jint (*)(void *)) JNI_GetDefaultJavaVMInitArgs_;
instance->JNI_CreateJavaVM = (jint (*)(JavaVM**, JNIEnv**, void*)) JNI_CreateJavaVM_;
instance->JNI_GetCreatedJavaVMs = (jint (*)(JavaVM**, jsize, jsize*)) JNI_GetCreatedJavaVMs_;
return true;
}
先看一下JniInvocationGetLibrary函数:
const char* JniInvocationGetLibrary(const char* library, char* buffer) {
bool debuggable = IsDebuggable();
const char* system_preferred_library = NULL;
if (buffer != NULL && (GetLibrarySystemProperty(buffer) > 0)) {
system_preferred_library = buffer;
}
//调用到JniInvocationGetLibraryWith函数中
return JniInvocationGetLibraryWith(library, debuggable, system_preferred_library);
}
const char* JniInvocationGetLibraryWith(const char* library,
bool is_debuggable,
const char* system_preferred_library) {
//是否debug
if (is_debuggable) {
// Debuggable property is set. Allow library providing JNI Invocation API to be overridden.
// Choose the library parameter (if provided).
if (library != NULL) {
return library;
}
// Choose the system_preferred_library (if provided).
if (system_preferred_library != NULL) {
return system_preferred_library;
}
}
//返回libart.so字段
return kDefaultJniInvocationLibrary;
}
再看一下DlOpenLibrary函数,源码位置在:./DlHelp.c:28行
DlLibrary DlOpenLibrary(const char* filename) {
#ifdef _WIN32
return LoadLibrary(filename);
#else
// Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
// This is due to the fact that it is possible that some threads might have yet to finish
// exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
// unloaded.
//加载的linux的dlopen函数
return dlopen(filename, RTLD_NOW | RTLD_NODELETE);
#endif
}
接着往下看,看一下FindSymbol函数的调用:
static DlSymbol FindSymbol(DlLibrary library, const char* symbol) {
//又调用了DlGetSymbol函数
DlSymbol s = DlGetSymbol(library, symbol);
if (s == NULL) {
ALOGE("Failed to find symbol: %s", symbol);
}
return s;
}
DlGetSymbol函数也在./DlHelp.c中第48行:
DlSymbol DlGetSymbol(DlLibrary handle, const char* symbol) {
#ifdef _WIN32
return (DlSymbol) GetProcAddress(handle, symbol);
#else
//调用的是linux的dlsym函数
return dlsym(handle, symbol);
#endif
}
通过以上分析,可以明确第2点,加载libart.so库,这个so库的源码位置再art/runtime/jni/java_vm_ext.cc中,这里就不做分析了。
启动虚拟机
顺着主线继续,然后再来分析第3步,启动虚拟机startVm的流程, 回到源码:/frameworks/base/core/jni/AndroidRuntime.cpp中:
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
JavaVMInitArgs initArgs;
//配置了很多虚拟机参数
...
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* Initialize the VM.
*
* The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
* If this call succeeds, the VM is ready, and we can start issuing
* JNI calls.
*/
//创建java虚拟机
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
return 0;
}
注册JNI函数
startReg方法调用主要是注册jni函数,下面看一下是如何注册的:
static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
...
env->PushLocalFrame(200);
//注册jni函数的方法,跟一下register_jni_procs函数
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
//通过for循环,注册全部jni函数
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
...
return -1;
}
}
return 0;
}
//将这些jni函数全部注册
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_CharsetUtils),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
REG_JNI(register_android_util_MemoryIntArray),
REG_JNI(register_android_app_admin_SecurityLog),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
REG_JNI(register_android_content_res_ApkAssets),
REG_JNI(register_android_text_AndroidCharacter),
REG_JNI(register_android_text_Hyphenator),
REG_JNI(register_android_view_InputDevice),
REG_JNI(register_android_view_KeyCharacterMap),
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
...
};
register_com_android_internal_os_RuntimeInit这些函数还可以继续往下分析,其实就是调用了jniEnv的RegisterNatives函数,这个函数在app动态注册函数时使用的是同一个方法,这里就不再继续深入了。
启动ZygoteInit
经过以上的加载虚拟机,注册jni函数完成后,终于通过反射启动了ZygoteInit.java的静态main方法入口,ZygoteInit源码位置:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
public static void main(String[] argv) {
//申明zygoteServer
ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
//抑制线程启动,保证zygote单线程启动
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group.
//设置进程组的id
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
...
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
//包含start-system-server,将startSystemServer置为true
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
//从AndroidRuntime.cpp中带过来的也有这个信息
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else ...
}
...
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
//enableLazyPreload是false
if (!enableLazyPreload) {
...
//加载android资源
preload(bootTimingsTraceLog);
...
}
// Do an initial gc to clean up after startup
//调用gc进行初始清理回收
gcAndFinalize();
//调用AppRuntime的onZygoteInit函数
Zygote.initNativeState(isPrimaryZygote);
//中止抑制子线程启动,即将fork,要保证线程可以创建线程
ZygoteHooks.stopZygoteNoThreadCreation();
//初始化ZygoteServer创建socket
zygoteServer = new ZygoteServer(isPrimaryZygote);
//此时startSystemServer为true,会启动systemServer
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.
//r==null时为zygote进程,r!=null时为子进程
if (r != null) {
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.
//在子进程中会有返回值,在zygote进程中永远循环
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
//出现异常或子进程返回,需要关闭socket
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the command.
//子进程返回后,会执行
if (caller != null) {
caller.run();
}
}
}
以上流程备注的比较详细了,下面针对其中的步骤做详细分析。
首先看一下ZygoteHooks.startZygoteNoThreadCreation(),禁止创建线程,之所以要禁止创建线程,是因为Zygote必须保证线程单一,这和fork机制有关,fork函数只会将当前线程复制到子进程,同时,fork会将锁也复制到子进程中,如果在fork之前,有一个线程持有了锁,但是fork的时候没把这个线程复制到子进程中,这把锁就被永久持有了,会造成死锁。
preload
接下来重点看一下加载android资源,进入到preload方法中看一下:
static void preload(TimingsTraceLog bootTimingsTraceLog) {
...
//预加载android中的java类
preloadClasses();
//加载三个jar
/* /system/framework/android.hidl.base-V1.0-java.jar */
/* /system/framework/android.hidl.manager-V1.0-java.jar */
/* /system/framework/android.test.base.jar */
cacheNonBootClasspathClassLoaders();
//预加载资源
preloadResources();
//加载硬件抽象层
nativePreloadAppProcessHALs();
//加载渲染相关opengl等
maybePreloadGraphicsDriver();
//加载动态库
preloadSharedLibraries();
//加载front库
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
//预加载webviewchromium
WebViewFactory.prepareWebViewInZygote();
...
}
先看一下源码:
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
InputStream is;
try {
is = new FileInputStream(PRELOADED_CLASSES);
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
return;
}
...
try {
BufferedReader br =
new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);
int count = 0;
int missingLambdaCount = 0;
String line;
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
line = line.trim();
//如果被注释或者是空的,直接continue
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
//加载类
Class.forName(line, true, null);
count++;
} catch (ClassNotFoundException e) {
...
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
...
}
}
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
IoUtils.closeQuietly(is);
//用预加载带来的类、字段和方法填充dex缓存
runtime.preloadDexCaches();
...
}
}
可以看到主要就是通过类加载器从/system/etc/preloaded-classes这个路径文件中预加载类,这个路径文件在源码的路径为:frameworks/base/config/preloaded-classes,可以进去看一下:
android.R$styleable
android.accessibilityservice.AccessibilityServiceInfo$1
android.accessibilityservice.AccessibilityServiceInfo
android.accessibilityservice.IAccessibilityServiceClient$Stub$Proxy
android.accessibilityservice.IAccessibilityServiceClient$Stub
android.accessibilityservice.IAccessibilityServiceClient
android.accounts.AbstractAccountAuthenticator$Transport
android.accounts.AbstractAccountAuthenticator
android.accounts.Account$1
android.accounts.Account
android.accounts.AccountAndUser
android.accounts.AccountAuthenticatorResponse$1
android.accounts.AccountAuthenticatorResponse
android.accounts.AccountManager$10
android.accounts.AccountManager$11
android.accounts.AccountManager$15
android.accounts.AccountManager$16
android.accounts.AccountManager$17
android.accounts.AccountManager$18
android.accounts.AccountManager$1
android.accounts.AccountManager$20
android.accounts.AccountManager$2
android.accounts.AccountManager$3
android.accounts.AccountManager$8
android.accounts.AccountManager$AmsTask$1
android.accounts.AccountManager$AmsTask$Response
android.accounts.AccountManager$AmsTask
android.accounts.AccountManager$BaseFutureTask$1
android.accounts.AccountManager$BaseFutureTask$Response
android.accounts.AccountManager$BaseFutureTask
android.accounts.AccountManager$Future2Task$1
android.accounts.AccountManager$Future2Task
android.accounts.AccountManager
android.accounts.AccountManagerCallback
...
为什么需要在zygote中预加载类呢?
这是由于父子进程的资源是共享的,每启动一个app,都需要使用虚拟机、加载类等,直接在父进程中预加载这些,fork后子进程就可以直接使用它们,就不需要每个app都要去加载一次,降低系统效率,浪费资源。
cacheNonBootClasspathClassLoaders
再看一下cacheNonBootClasspathClassLoaders加载了三个jar
private static void cacheNonBootClasspathClassLoaders() {
// These libraries used to be part of the bootclasspath, but had to be removed.
// Old system applications still get them for backwards compatibility reasons,
// so they are cached here in order to preserve performance characteristics.
//这些库曾经是bootclasspath的一部分,但必须删除,由于向后兼容性的原因,旧的系统应用程序仍然得到它们,所以缓存再这里
SharedLibraryInfo hidlBase = new SharedLibraryInfo(
"/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/,
null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
false /*isNative*/);
SharedLibraryInfo hidlManager = new SharedLibraryInfo(
"/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/,
null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
false /*isNative*/);
SharedLibraryInfo androidTestBase = new SharedLibraryInfo(
"/system/framework/android.test.base.jar", null /*packageName*/,
null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
false /*isNative*/);
ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders(
new SharedLibraryInfo[]{
// ordered dependencies first
hidlBase,
hidlManager,
androidTestBase,
});
}
preloadResources
preloadResources主要预加载资源和检查资源
private static final boolean PRELOAD_RESOURCES = true;
private static void preloadResources() {
try {
mResources = Resources.getSystem();
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
//加载所有drawable
TypedArray ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(ar);
ar.recycle();
//加载color属性
ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(ar);
ar.recycle();
...
}
mResources.finishPreloading();
} catch (RuntimeException e) {
Log.w(TAG, "Failure preloading resources", e);
}
}
private static int preloadDrawables(TypedArray ar) {
int N = ar.length();
for (int i = 0; i < N; i++) {
int id = ar.getResourceId(i, 0);
if (id != 0) {
//
if (mResources.getDrawable(id, null) == null) {
throw new IllegalArgumentException(
"Unable to find preloaded drawable resource #0x"
+ Integer.toHexString(id)
+ " (" + ar.getString(i) + ")");
}
}
}
return N;
}
private static int preloadColorStateLists(TypedArray ar) {
int N = ar.length();
for (int i = 0; i < N; i++) {
int id = ar.getResourceId(i, 0);
if (id != 0) {
if (mResources.getColorStateList(id, null) == null) {
throw new IllegalArgumentException(
"Unable to find preloaded color resource #0x"
+ Integer.toHexString(id)
+ " (" + ar.getString(i) + ")");
}
}
}
return N;
}
直接上面分析了几种,其他项基本都是预加载各种资源,就不再一个一个的看了,接着主线流程,往preload下面看:
ZygoteServer
可以看到调用两次创建socket的方法,传入不同的参数,分别创建了一个socket
java
//ZygoteServer的构造方法,此时isPrimaryZygote为true
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
//创建本地socket,传入zygote
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
//创建本地socket,传入usap_pool_primary
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
//创建本地socket,传入zygote_secondary
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
//创建本地socket,传入usap_pool_secondary
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
调用了Zygote.java中的静态方法,接着往下追代码:
java
/** Prefix prepended to socket names created by init */
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
/**
* @hide for internal use only.
*/
public static final String PRIMARY_SOCKET_NAME = "zygote";
/**
* @hide for internal use only.
*/
public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
/**
* @hide for internal use only
*/
public static final String USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary";
/**
* @hide for internal use only
*/
public static final String USAP_POOL_SECONDARY_SOCKET_NAME = "usap_pool_secondary";
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//获取指定环境变量fullSocketName的值
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
//创建fd并绑定节点
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//创建LocalServerSocket对象,并传入fd
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
进入到LocalServerSocket类中,其中又创建了LocalSocketImpl对象,然后设置了fd和BACKLOG为50的监听:
java
private static final int LISTEN_BACKLOG = 50;
public LocalServerSocket(FileDescriptor fd) throws IOException
{
//创建LocalSocketImpl对象
impl = new LocalSocketImpl(fd);
//添加监听,监听BACKLOG为50
impl.listen(LISTEN_BACKLOG);
//获取本地地址
localAddress = impl.getSockAddress();
}
LocalSocketImpl构造方法什么都没干,listene方法内部就是调用的Os.listen(FileDescriptor fd, int backlog),就不再往下分析了。
forkSystemServer
java
//传入的参数:架构, zygote, zygoteServer对象
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
...
/* Hardcoded command line to start the system server */
//fork内容要传入的参数
String[] args = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs;
int pid;
try {
ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
try {
parsedArgs = ZygoteArguments.getInstance(commandBuffer);
} catch (EOFException e) {
throw new AssertionError("Unexpected argument error for forking system server", e);
}
commandBuffer.close();
...
/* Enable gwp-asan on the system server with a small probability. This is the same
* policy as applied to native processes and system apps. */
parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;
if (shouldProfileSystemServer()) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
//进入到zygote的静态方法中
pid = Zygote.forkSystemServer(
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) {
if (hasSecondZygote(abiList)) {
//等待secondZygote
waitForSecondaryZygote(socketName);
}
//停止自己的serverSocket
zygoteServer.closeServerSocket();
//调用了handleSystemServerProcess
return handleSystemServerProcess(parsedArgs);
}
return null;
}
//Zygote.forkSystemServer
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
//调用了nativeForkSystemServer,这是一个native方法,可以通过命令搜索源码
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Set the Java Language thread priority to the default value for new apps.
//设置新进程的线程优先级
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
通过如下命令搜索:
java
grep nativeForkSystemServer ./ -rn
进入到nativeForkSystemServer源码中:
java
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) {
...
//调用了zygote的ForkCommon方法,再跟一下
pid_t pid = zygote::ForkCommon(env, true,
fds_to_close,
fds_to_ignore,
true);
if (pid == 0) {
// System server prcoess does not need data isolation so no need to
// know pkg_data_info_list.
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false,
/* pkg_data_info_list */ nullptr,
/* allowlisted_data_info_list */ nullptr, false, false);
}
return pid;
}
//ForkCommon
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
const std::vector<int>& fds_to_close,
const std::vector<int>& fds_to_ignore,
bool is_priority_fork,
bool purge) {
//设置子进程信号处理函数
SetSignalHandlers();
...
//fork前先阻塞SIGCHLD信号
BlockSignal(SIGCHLD, fail_fn);
...
//最终是调用了fork方法
pid_t pid = fork();
...
// We blocked SIGCHLD prior to a fork, we unblock it here.
//恢复SIGCHLD信号
UnblockSignal(SIGCHLD, fail_fn);
return pid;
}
这里佐证了forkSystemServer是通过fork来实现的进程启动,forSystemServer返回值是一个Runnable,看一下这个Runnable怎么被创建出来的,可以看到再pid==0子进程创建成功后,调用了handleSystemServerProcess,看一下源码:
java
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
//设置权限掩码
Os.umask(S_IRWXG | S_IRWXO);
//设置进程名称为system_server
if (parsedArgs.mNiceName != null) {
Process.setArgV0(parsedArgs.mNiceName);
}
...
if (parsedArgs.mInvokeWith != null) {
...
} else {
//创建classloader
ClassLoader cl = getOrCreateSystemServerClassLoader();
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
//调用了ZygoteInit.zygoteInit方法
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
}
进入到zygoteInit方法中:
java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
//调用到了RuntimeInit.applicationInit
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
调用到了RuntimeInit.applicationInit,继续追踪
java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
....
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
//调用findStaticMain, 查找main方法,在追踪一下
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
//findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
//反射获取类对象
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
//反射获取main方法对象
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
//new MethodAndArgsCaller其实就是一个Runnable,其中的run方法就是invoke这个main方法,可以通过源码印证
return new MethodAndArgsCaller(m, argv);
}
//MethodAndArgsCaller
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
//run方法,调用后会调用main方法
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
整个过程就是调用到了SystemServer的main方法中启动了SystemServer,SystemServer启动后做了什么留在后面章节分析,这里继续将剩余的流程分析完。
runSelectLoop
ZygoteInit类中如果startSystemServer为false,则会调用zygoteServer.runSelectLoop方法,看一下这个方法做了什么:
java
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//将server socket fd加到列表头(后面需要判断是否为server socket)
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
...
//等待fd的事件
try {
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
//pollIndex == 0说明fd是ZygoteServer socket的fd
if (pollIndex == 0) {
// Zygote server socket
//接受并建立一个socket连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
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);
final Runnable command = connection.processOneCommand(this);
// 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);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
// We're in the server so any exception here is one that has taken place
// pre-fork while processing commands or reading / writing from the
// control socket. Make a loud noise about any such exceptions so that
// we know exactly what failed and why.
Slog.e(TAG, "Exception executing zygote command: ", e);
// Make sure the socket is closed so that the other end knows
// immediately that something has gone wrong and doesn't time out
// waiting for a response.
ZygoteConnection conn = peers.remove(pollIndex);
conn.closeSocket();
socketFDs.remove(pollIndex);
} else {
// We're in the child so any exception caught here has happened post
// fork and before we execute ActivityThread.main (or any other main()
// method). Log the details of the exception and bring down the process.
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the Runnable
// is returned.
mIsForkChild = false;
}
} else {
// Either the USAP pool event FD or a USAP reporting pipe.
// If this is the event FD the payload will be the number of USAPs removed.
// If this is a reporting pipe FD the payload will be the PID of the USAP
// that was just specialized.
long messagePayload = -1;
try {
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream.readLong();
} else {
Log.e(TAG, "Incomplete read from USAP management FD of size "
+ readBytes);
continue;
}
} catch (Exception ex) {
if (pollIndex == usapPoolEventFDIndex) {
Log.e(TAG, "Failed to read from USAP pool event FD: "
+ ex.getMessage());
} else {
Log.e(TAG, "Failed to read from USAP reporting pipe: "
+ ex.getMessage());
}
continue;
}
if (pollIndex > usapPoolEventFDIndex) {
Zygote.removeUsapTableEntry((int) messagePayload);
}
usapPoolFDRead = true;
}
}
// Check to see if the USAP pool needs to be refilled.
if (usapPoolFDRead) {
int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(fd -> fd.getInt$())
.toArray();
final Runnable command = fillUsapPool(sessionSocketRawFDs);
if (command != null) {
return command;
}
}
}
}
未完待续...