DVM与ART的区别?
5.0后Android runtime由DVM改成ART,区别是?
DVM:
应用运行时,即时编译器将字节码编译成机器码,使得应用运行效率低
ART:
应用安装时,提前进行一次预编译,将字节码编译成机器码存储在本地,这样应用运行时就不用再编译一次了,运行效率大大提高。
Android 系统启动过程
Android 系统启动过程涉及到很多系统进程的启动以及各类服务的创建,首先来看一下总的过程概览:
步骤一 启动init进程
Android从按下电源到启动会经过很多个步骤,现在一个个的来看,首先启动的是init进程,它是用户空间的第一个进行,进程号为1;init进程主要做三件事:
- 创建和挂载启动所需的文件目录
- 初始化和启动属性服务
- 解析init.rc配置文件且启动Zygote进程
步骤二 启动Zygote进程
zygote是啥?
init进程启动后,会创建一个zygote进程,然后由这个zygote进程去创建DVM、ART虚拟机、应用程序进程以及运行系统关键服务的SystemServer,zygote创建时就会创建DVM、ART,再通过fork(叉子)去创建应用程序进程以及SystemServer.
fork进程是什么意思?
可以理解为克隆,父进程通过fork创建出子进程,子进程是父进程的副本,可以获得父进程的数据空间、堆、栈的副本,不与父进程共享存储空间。
init进程经过Runtime,通过JNI调用zygote的ZygoteInit类的main()方法,zygote得以从Native层进入Java框架层,可以在studio中看到ZygoteInit类以及对应的main()方法,这个main()方法主要做几件事:
//1.创建一个Server端的socket,名为zygote,内部就是启动一个LocalServerSocket。
zygoteServer.registerServerSocket(socketName);
//2.预加载类和资源
preload(bootTimingsTraceLog);
//3.启动SystemServer进程,系统服务也因此启动起来
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
//4.等待AMS请求zygote创建新的应用程序进程。
zygoteServer.runSelectLoop(abiList);
具体看下如何启动SystemServer?
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller, RuntimeException {
//1.创建args数组,用于补充Systemserver的启动参数,例如uid、pid、群组,进程名,可见用户id和用户组id均是1000,且拥有用户组1000~1010,1021、1032、3001~3010的权限
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",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//2.Zygote通过fork创建一个子进程,即创建一个Zygote进程的子进程SystemServer
pid = Zygote.forkSystemServer(param);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//3.表明当前代码运行在子进程中
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
//因为子进程是复制出来的,所以也有一个socket,但是对于SystemServer是没用的,所以close()
zygoteServer.closeServerSocket();
//4.处理SystemServer进程
handleSystemServerProcess(parsedArgs);
}
return true;
}
再来看下如何通过runSelectLoop来等待AMS创建应用程序进程?
死循环等待AMS的请求,有了请求,就去创建新的应用程序进程,并添加到链接列表中。
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//1.这个mServerSocket就是第一步中创建的服务端Socket
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
//无限循环等待AMS的请求zygote进程创建新的应用进程
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
//2.将文件描述符数组fds转移到pollFds数组
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
//3.遍历pollFds,如果i == 0,说明服务端socket和客户端链接上了,即zygote进程和AMS建立了链接
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
//4.添加该connection到peers列表中
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//5.如果i != 0,说明AMS向zygote发来一个新的创建应用程序进程请求,则调用runOnce()创建一个,创建成功,从列表中删除该链接。
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
SystemServer的处理过程
上面创建SystemServer的过程中,有一行代码:
handleSystemServerProcess(parsedArgs); //干什么的?这行代码会调用到ZygoteInit的zygoteInit()方法,去看看这个方法做了什么事情?
zygoteInit()
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit(); //这里调用了native的方法,用来启动Binder线程池,这样一来,SystemServer进程就可以使用Binder与其他进程进行通信了。前面所有流程中,Binder还没创建。
//进入SystemServer的main方法
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
1.如何启动Binder线程池
ZygoteInit.nativeZygoteInit()的代码位于frameworks/base/core/jni/AndroidRuntime.cpp中,内部调用的是frameworks/base/cmds/app_process/app_main.cpp的onZygoteInit()方法,具体如下:
virtual void onZygoteInit(){
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool(); //通过调用ProcessState的startThreadPool()来创建Binder线程池
}
ProcessState创建Binder线程池的具体代码:
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain); //创建线程并运行
t->run(name.string());
}
}
2.SystemServer进程如何启动系统服务?
直接来看看SystemServer的main()方法:
public static void main(String[] args) {
new SystemServer().run(); //这里只是调用了它的run()方法,那它的run()方法又做了啥?
}
run():
private void run() {
try {
...
//创建消息Looper
Looper.prepareMainLooper();
// 1. 加载了动态库libandroid_servers.so
System.loadLibrary("android_servers");
performPendingShutdown();
//创建系统的Context
createSystemContext();
// 2.创建系统ServiceManager,它是对系统服务进行创建、启动以及生命周期管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
SystemServerInitThreadPool.get();
} finally {
traceEnd();
}
try {
traceBeginAndSlog("StartServices");
//3. 启动引导服务,这里很重要,通过mSystemServiceManager去启动AMS、PMS
startBootstrapServices();
//4. 启动核心服务,例如BatteryService、WebViewUpdateService
startCoreServices();
//5.启动其他服务,例如CameraService、WMS,这些服务的父类均为SystemService.都是通过mSystemServiceManager.startService(“ServiceName”.class)来创建
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
SystemServiceManager如何创建各类Service,去看看它的startService():
public void startService(@NonNull final SystemService service) {
// 所有创建的Service都要添加到一个ArrayList中方便管理
mServices.add(service);
// Start it.
long time = System.currentTimeMillis();
try {
//启动Service
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
}
也可以通过具体Service的main()方法来创建,例如PackageManagerService.main()
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// 初始化设置检测
PackageManagerServiceCompilerMapping.checkProperties();
//1. 直接new一个示例
PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
m.enableSystemUserPackages();
//2.添加到ServiceManager中
ServiceManager.addService("package", m);
return m;
}
ServiceManager用来管理各种Service,当client要使用Service时,先去 ServiceManager查询该Service的相关信息,然后根据该Service的相关信息以及所在进程和client建立通信通道,这样client就可以使用service了。
步骤三 启动Launcher
系统启动的最后一步,启动一个应用程序显示系统中所有已安装的应用程序,这个应用程序就是Launcher,它在启动时会去向PackageManagerService请求获取所有安装的应用程序,并将所有应用程序的快捷图标显示在桌面上,这样用户就可以通过点击图标来启动指定的应用程序。
可以认为Launcher就是android的桌面,它主要做2个事情:
- 显示和管理应用程序的快捷图标
- 用于启动应用程序
Launcher启动过程介绍:
- 启动入口 : AMS的systemReady方法,代码如下,在SystemServer的startOtherServices()中:
private void startOtherServices() {
...
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
traceEnd();
...
}
...
- 看一下AMS的syatemReady():
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
...
synchronized(this) {
mStackSupervisor.resumeFocusedStackTopActivityLocked(); //这里又进入了StackSupervisor的resumeFocusedStackTopActivityLocked()
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
...
}
- 那么在StackSupervisor的resumeFocusedStackTopActivityLocked()又做了什么?
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); //这中间经过一系列的跳转,会进入到ActivityStackSupervisor的resumeHomeStackTask()中
}
...
return false;
}
- ActivityStackSupervisor的resumeHomeStackTask()又做了什么?
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
...
if (prev != null) {
prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
}
mHomeStack.moveHomeStackTaskToTop();
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
// Only resume home activity if isn't finishing.
if (r != null && !r.finishing) {
moveFocusableActivityStackToFrontLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser, myReason); //主要工作就是调用AMS去启动HomeActivity
}
- AMS的startHomeActivityLocked()方法:
boolean startHomeActivityLocked(int userId, String reason) {
//1. mFactoryTest代表系统的运行模式,分为非工厂模式、低级工厂模式、高级工厂模式,mTopAction表示第一个启动的activity的action,默认是:Intent.ACTION_MAIN.
//如果mFactoryTest为低级工厂模式,且mTopAction == null不符合下面要求,则返回false
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL&& mTopAction == null) {
return false;
}
//2. 这里返回了一个category为Intent.CATEGORY_HONE的intent
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid, true);
//3. 判断Action为 Intent.ACTION_MAIN且Category为 Intent.CATEGORY_HONE的应用程序是否已经启动,没有则调用4的方法进行启动,这个程序就是Launcher,可以从它的 // AndroidManifest.xml文件里面查看它的定义的intent-fliter。
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
//4.调用ActivityStarter的startHomeActivityLocked来启动Launcher
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
- ActivityStarter的startHomeActivityLocked来启动Launcher
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
// 1. 将Launcher放入HomeStack中, HomeStack是ActivityStackSupervisor中用于存储Launcher的变量。
mSupervisor.moveHomeStackTaskToTop(reason);
// 2.调用startActivityLock()来启动Launcher,和正常启动Activity的过程一样。
mLastHomeActivityStartResult = startActivityLocked(...params);
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}
至此,就完成了Launcher的启动。Android整个系统的启动过程也大致完毕。