在《Android系統啟動之Zygote》的中,我們知道SystemServer程序(程序名為system_server)是由Zygote程序fork出來的,但當時并沒有說明SystemServer.main()方法是怎樣被調用的,說到這裡不知道大家有沒有想過一個問題,我們在寫一個Android demo應用的時候,為什麼都沒見過main()方法,而在寫一個java demo時就要實作main()方法。這個問題大家可以想一想,以後有機會再講解。那麼還是回歸正題,這篇文章我們還是來了解下SystemServer.main()是怎樣被調用的。
我們知道system_server程序是有Zygote fork出來的,在ZygoteInit.forkSystemServer()方法中完成了具體的實作,關于fork出system_server的後續流程,我們先放一張時序圖總結下。
接下來,我們從ZygoteInit.forSystemServer()方法一步步往下分析
forSystemServer
//framework/base/core/java/com/android/internal/os/ZygoteInit.java
/**
* Prepare the arguments and forks for the system server process.
*
* Returns an {@code Runnable} that provides an entrypoint into system_server code in the
* child process, and {@code null} in the parent.
*/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
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,
OsConstants.CAP_WAKE_ALARM
);
/* Containers run without this capability, so avoid setting it in that case */
if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
}
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server", //system_server就是程序名
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
//Zygote.forkSystemServer會傳回兩次,分别是在子程序和父程序中
//pid ==0 表示目前在子程序,也就是fork出來的system_server程序。
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
關于Zygote.forkSystemServer()具體流程就不展開,感興趣的可以可以根據《Android系統啟動之Zygote》文章最後的時序圖看下有關方法的具體實作。目前在子線程也就是system_server中時,就會進入上面的
if(pid==0)
判斷語句。
handleSystemServerProcess
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
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);
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it.
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);
}
}
}
//在forkSystemServer()方法中沒有配置“--invoke-with",是以此時parsedArgs.invokeWith = null;
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
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);
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
Os.getenv("SYSTEMSERVERCLASSPATH");
會擷取SYSTEMSERVERCLASSPATH環境變量,最終實作是在libcore_io_Linux.cpp中的jni方法getenv()函數。也可以通過adb shell 環境下輸入env指令檢視,該指令可以檢視所有環境變量。
在得到
SYSTEMSERVERCLASSPATH
值之後,會進行dex優化。
zygoteInit
//framework/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
//将log重定向到Android log輸出
RuntimeInit.redirectLogStreams();
//初始化,包括設定未捕獲異常處理,設定時區,重置log,設定Http user agent和設定socket的tag
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
在zygoteInit()方法中會調用靜态方法nativeZygoteInit(),該方法通過jni方式最終會調用app_main.cpp中的onZygoteInit()函數,在該函數中主要是打開binder驅動并建立binder線程。
//framework/base/cmd/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
//framework/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
RuntimeInit.applicationInit()
接下來我們看下Runtime.applicationInit()方法的實作,在該方法中先調用了nativeSetExitWithoutCleanup(),這會影響當應用退出時是否會調用AndroidRuntime::onExit()函數;然後設定了虛拟機記憶體使用率;最後調用findStaticMain()方法,通過反射的方式找到SystemServer.main()方法的Method對象,不過這個時候并沒有調用SystemServer.main()方法,而是将它的Method對象和argv封裝成MethodAndArgsCaller對象。
//framework/base/core/java/com/android/internal/os/RuntimeInit.java
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.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
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
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
private 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);
}
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);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}
MethodAndArgsCaller實作了Runnable接口,在該對象的run()方法中才會通過Method.invoke()方法真正調用ZygoteInit.main()方法中。
//framework/base/core/java/com/android/internal/os/ZygoteInit.java
//main()方法調用MethodAndArgsCaller.run()
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;
}
}
不知道細心的同學有沒有發現一個小小的問題,在RuntimeInit.findStaticMain()方法的最後的注釋說抛出異常以便在ZygoteInit.main()方法中捕獲,然後調用MethodAndArgsCaller.run()方法,然而實際在findStaticMain()最後是傳回 MethodAndArgsCaller對象的,在ZygoteInit.main()方法中也不是在捕獲異常的時候調用MethodAndArgsCaller.run()方法的,而是在forkSystemServer()方法傳回Runnable對象後調用其run()方法,并不是如注釋中說明的那樣。這個地方其實是google工程師的鍋,在Android8.1之前是通過抛出異常,然後在ZygoteInit.main()方法中捕獲到異常後再調用MethodAndArgsCaller的run()方法(PS: Android8.1之前MethodAndArgsCaller繼承了Exception并實作了Runnable接口),但在Android8.1開始已修改為傳回MethodAndArgsCaller對象,然而注釋并沒有修改,其實直到Android10這個注釋也還沒修改。