安卓8 SystemServer启动源码分析笔记(一)
本文分析了Android系统中Zygote进程孵化SystemServer的过程。关键流程包括:1)Zygote通过forkSystemServer创建SystemServer进程;2)子进程调用handleSystemServerProcess方法返回Runnable对象;3)通过zygoteInit方法执行通用初始化,包括启动Binder线程池;4)使用findStaticMain方法反射获取
注意:学习本章知识需要安卓8 Zygote源码分析笔记这篇文章的知识作为铺垫。
前文回顾:
Android8 Zygote源码分析学习笔记(二)-CSDN博客文章浏览阅读575次,点赞16次,收藏15次。本文分析了Android系统中Zygote服务的核心流程,重点包括:1)Zygote通过init.zygote32.rc配置文件启动,由app_process程序运行;2)ZygoteInit类的main方法创建ZygoteServer并注册监听socket;3)预加载系统资源(类、库等);4)关键forkSystemServer方法创建系统服务进程的过程,涉及权限设置、资源限制配置等;5)runSelectLoop方法实现多路复用监听fork请求。源码分析揭示了Zygote作为"孵化器"https://blog.csdn.net/g_i_a_o_giao/article/details/150764611?spm=1011.2124.3001.6209Android8 Zygote源码分析学习笔记(一)-CSDN博客文章浏览阅读110次,点赞3次,收藏2次。本文分析了Android系统Zygote服务的启动流程。Zygote通过init.zygote32.rc配置文件启动,由app_process程序以root权限运行,参数中包含"--zygote"和"--start-system-server"标志。源码分析从app_main.cpp的main函数开始,解析参数后创建AppRuntime对象并调用其start方法,最终通过JNI调用ZygoteInit类的main方法。关键步骤包括参数解析、虚拟机启动、JNI方法注册,
https://blog.csdn.net/g_i_a_o_giao/article/details/150613561?spm=1011.2124.3001.6209接之前文章的分析,当SystemServer的进程被fork出来以后,会调用handleSystemServerProcess方法来返回一个Runnable对象。
try {
/* 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);
}/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
那么来看看这个handleSystemServerProcess方法。在这个方法中,首先是获取系统服务类路径的环境变量,然后进行优化和性能分析(这里不是重点就不分析了),然后就是创建系统服务的类加载器。最后就是调用ZygoteInit的zygoteInit方法。
/**
* Finish remaining work for the newly forked system server process.
*/
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// 设置umask为0077,确保新创建的文件和目录默认只有所有者有权限(组和其他用户无权限)
Os.umask(S_IRWXG | S_IRWXO);
// 如果指定了进程的友好名称,设置进程名称
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
// 获取系统服务类路径环境变量(重要)
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
// 对系统服务类路径中的Dex文件执行优化
performSystemServerDexOpt(systemServerClasspath);
// 仅在调试或工程版本中支持性能分析捕获,因为SELinux通常会阻止此操作
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
try {
// 创建性能分析文件目录
File profileDir = Environment.getDataProfilesDePackageDirectory(
Process.SYSTEM_UID, "system_server");
File profile = new File(profileDir, "primary.prof");
profile.getParentFile().mkdirs();
profile.createNewFile();
// 将类路径拆分为数组
String[] codePaths = systemServerClasspath.split(":");
// 向运行时注册应用信息以启用性能分析
VMRuntime.registerAppInfo(profile.getPath(), codePaths);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
// 如果指定了调用包装器(如使用wrap.sh脚本)
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// 如果有系统服务类路径,需要复制现有参数并追加类路径
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(args, 0, amendedArgs, 2, args.length);
args = amendedArgs;
}
// 使用包装器执行应用
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
// 正常情况下不会执行到此,因为execApplication会替换当前进程
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
// 没有使用调用包装器的正常路径
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 为系统服务创建路径类加载器
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
// 设置当前线程的上下文类加载器
Thread.currentThread().setContextClassLoader(cl);
}
/*
* 将剩余参数传递给SystemServer
*/
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
打开模拟器后运行adb shell env命令可以看到SYSTEMSERVERCLASSPATH的变量值为:
SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar
那么再来看看zygoteInit方法。在这个方法中,主要的还是调用RuntimeInit.commonInit方法以及RuntimeInit的applicationInit方法。
/**
* 当通过zygote进程启动时调用的主要函数。如果nativeFinishInit()中的本地代码与Zygote启动
* 合理化,这个函数可以与main()统一。
*
* 当前识别的参数:
* <ul>
* <li> <code> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion 目标SDK版本
* @param argv 参数字符串数组
* @param classLoader 类加载器
* @return 可运行对象,通常是调用主类的main方法
*/
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
// 调试模式下记录日志
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
// 开始性能跟踪,标记为ActivityManager相关
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
// 重定向标准输出和标准错误流到Android日志系统
RuntimeInit.redirectLogStreams();
// 执行通用的运行时初始化
RuntimeInit.commonInit();
// 执行本地层的Zygote初始化(启动Binder线程池等)
ZygoteInit.nativeZygoteInit();
// 执行应用特定的初始化并返回Runnable对象
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
很明显我们又要去到RuntiimeInit这个类中去查看applicationInit方法。在这个方法中,还是进行了一系列的设置,然后解析参数,最后我们又看到了熟悉的findStaticMain方法,看这个名字就知道又要去找对应类的静态main方法了。
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
// 设置原生退出标志,使System.exit()立即终止进程而不运行关闭钩子
// 这是因为Android应用无法优雅关闭,运行时关闭钩子会关闭Binder驱动,
// 可能导致残留的运行线程在进程实际退出前崩溃
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
/ 设置堆内存利用率为0.75,表示垃圾回收器会在堆内存使用达到75%时尝试回收内存
// 这是一种相对激进的内存管理策略,避免持有大量不需要的内存
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
// 设置应用程序的目标SDK版本,这会影响虚拟机的兼容性行为
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
// 查找并返回启动类的静态main方法包装器
// 剩余的参数将传递给启动类的静态main方法
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
然后继续分析findStaticMain方法。在这个类中主要是通过类加载器反射获取指定类的main函数以及它的修饰符,最后创建了一个MethodAndArgsCaller对象并且返回。然后我自己在这个方法中添加了一句Slog.d(RuntimeInit.TAG, "Finding static main for class: " + className);来看看加载了哪些类的静态方法,主要有ActivityThread和SystemServer等类。
/**
* 调用类"className"上的静态"main(argv[])"方法。
* 将各种失败异常转换为RuntimeException,假定这会导致VM实例退出。
*
* @param className 完全限定的类名
* @param argv 传递给main()方法的参数数组
* @param classLoader 用于加载{@className}的类加载器
* @return 一个Runnable对象,当运行时将调用类的静态main方法
*/
private static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
// 打印一下看看加载了哪些类
Slog.d(RuntimeInit.TAG, "Finding static main for class: " + className);
try {
// 使用提供的类加载器加载指定类
// 第二个参数true表示在加载时进行初始化(执行静态代码块)
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
// 如果类不存在,抛出运行时异常
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 获取类的main方法,它应该有一个String[]类型的参数
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
// 如果没有找到main方法,抛出运行时异常
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
// 如果没有访问方法的权限,抛出运行时异常
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
// 获取方法的修饰符(public、static等)
int modifiers = m.getModifiers();
// 检查方法是否是public和static的
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* 这个throw会在ZygoteInit.main()中被捕获,该函数通过调用异常的run()方法来响应。
* 这种安排清除了设置进程所需的所有堆栈帧。
*/
return new MethodAndArgsCaller(m, argv);
}
08-26 23:08:05.145 1547 1547 D AndroidRuntime: Finding static main for class: com.android.server.SystemServer
08-26 23:08:08.669 1893 1893 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:08:08.675 1904 1904 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:08:08.727 1985 1985 D AndroidRuntime: Finding static main for class: android.webkit.WebViewLibraryLoader$RelroFileCreator
08-26 23:08:08.731 1993 1993 D AndroidRuntime: Finding static main for class: android.webkit.WebViewLibraryLoader$RelroFileCreator
08-26 23:08:08.993 2089 2089 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:08:08.997 2102 2102 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:07:53.255 2159 2159 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:07:53.611 2196 2196 D AndroidRuntime: Finding static main for class: android.app.ActivityThread
08-26 23:07:53.795 2223 2223 D AndroidRuntime: Finding static main for class:
..................省略..................
继续分析MethodAndArgsCaller这个内部类。在这个类继承自Runnable类,在它的run方法中会通过反射调用各个类的静态main方法。可以将这个类理解为一个跳板,将各个类的main函数封装到Runnable中。
/**
* 辅助类,用于保存方法和参数并能够调用它们。
* 这部分用作蹦床(trampoline)的一部分,以消除初始进程设置堆栈帧。
*/
static class MethodAndArgsCaller implements Runnable {
/** 要调用的方法 */
private final Method mMethod;
/** 参数数组 */
private final String[] mArgs;
/**
* 构造函数
* @param method 要调用的方法(通常是main方法)
* @param args 传递给方法的参数数组
*/
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
/**
* 执行方法调用
* 当这个Runnable运行时,它会通过反射调用存储的方法
*/
public void run() {
try {
// 调用静态方法(第一个参数为null),传递参数数组
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);
}
}
}
这个跳板会一步一步的被返回,从findStaticMain->applicationInit->zygoteInit->handleSystemServerProcess->forkSystemServer。
回顾之前ZygoteInit类中的main函数,在调用forkSystemServer之后返回的正是runnable对象,然后就调用了run方法,也就是说这个跳板被使用了,最终执行到了对应服务类中的静态main函数。
ZygoteInit中的main函数:
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
// 重要
r.run();
return;
}
}
更多推荐
所有评论(0)