在Android的应用框架中,ActivityManagerService是非常重要的一个组件,尽管名字叫做ActivityManagerService,但通过之前的博客介绍,我们知道,四大组件的创建都是有AMS来完成的,其实不仅是应用程序中的组件,连Android应用程序本身也是AMS负责启动的。AMS本身运行在一个独立的进程中,当系统决定要在一个新的进程中启动一个Activity或者Service时就会先启动这个进程。而AMS启动进程的过程是从startProcessLocked启动的。
1.ActivityManagerService.startProcessLocked
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ...... private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { ...... try { int uid = app.info.uid; int[] gids = null; try { gids = mContext.getPackageManager().getPackageGids( app.info.packageName); } catch (PackageManager.NameNotFoundException e) { ...... } ...... int debugFlags = 0; ...... int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null, uid, uid, gids, debugFlags, null); ...... } catch (RuntimeException e) { ...... } } ...... }
可以看到,函数会调用Process.start函数来创建一个进程,其中第一个参数”android.app.ActivityThread”是需要加载的类,而在完成这个类的加载之后就会运行ActivityThread.main函数。
2.Process.start
public class Process { ...... public static final int start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, String[] zygoteArgs) { if (supportsProcesses()) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, zygoteArgs); } catch (ZygoteStartFailedEx ex) { ...... } } else { ...... return 0; } } ...... }
这个函数最后会调用startViaZygote来创建进程,而Zygote正是Android孵化进程的服务,所有的进程都是通过Zygotefork出来的,所以这里创建进程的任务又落到了Zygote头上了。
3.Process.startViaZygote
public class Process { ...... private static int startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, String[] extraArgs) throws ZygoteStartFailedEx { int pid; synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // --runtime-init, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-init"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { argsForZygote.add("--enable-safemode"); } if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) { argsForZygote.add("--enable-debugger"); } if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { argsForZygote.add("--enable-checkjni"); } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } //TODO optionally enable debuger //argsForZygote.add("--enable-debugger"); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } pid = zygoteSendArgsAndGetPid(argsForZygote); } } ...... }
函数里面最为重要的工作就是组装argsForZygote参数,这些参数将告诉Zygote具体的启动选项,例如”–runtime-init”就表示要为新启动的运行程序初始化运行库。然后调用zygoteSendAndGetPid函数进一步操作。
4.Process.zygoteSendAndGetPid
public class Process { ...... private static int zygoteSendArgsAndGetPid(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; openZygoteSocketIfNeeded(); try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure. */ sZygoteWriter.write(Integer.toString(args.size())); sZygoteWriter.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } sZygoteWriter.write(arg); sZygoteWriter.newLine(); } sZygoteWriter.flush(); // Should there be a timeout on this? pid = sZygoteInputStream.readInt(); if (pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } } catch (IOException ex) { ...... } return pid; } ...... } 这里的sZygoteWriter
是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的。而这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。这个类会返回一个ZygoteConnection实例,并执行ZygoteConnection的runOnce函数。
5.ZygoteConnection.runOnce
class ZygoteConnection { ...... boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { ...... return true; } ...... /** the stderr of the most recent request, if avail */ PrintStream newStderr = null; if (descriptors != null && descriptors.length >= 3) { newStderr = new PrintStream( new FileOutputStream(descriptors[2])); } int pid; try { parsedArgs = new Arguments(args); applyUidSecurityPolicy(parsedArgs, peer); applyDebuggerSecurityPolicy(parsedArgs); applyRlimitSecurityPolicy(parsedArgs, peer); applyCapabilitiesSecurityPolicy(parsedArgs, peer); int[][] rlimits = null; if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); } pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits); } catch (IllegalArgumentException ex) { ...... } catch (ZygoteSecurityException ex) { ...... } if (pid == 0) { // in child handleChildProc(parsedArgs, descriptors, newStderr); // should never happen return true; } else { /* pid != 0 */ // in parent...pid of < 0 means failure return handleParentProc(pid, descriptors, parsedArgs); } } ...... }
真正创建进程的代码在Zygote.forkAndSpecialize,通过Zygote来fork出一个新的进程作为应用进程。fork函数会有两个返回,其中一个在父进程,一个在子进程,其中自进程的进程号会为0,所以按照上面的代码,这里会执行handleChildProc。
6.ZygoteConnection.handleChildProc
class ZygoteConnection { ...... private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { ...... if (parsedArgs.runtimeInit) { RuntimeInit.zygoteInit(parsedArgs.remainingArgs); } else { ...... } } ...... }
因为在创建的时候传入了“–runtime-init”,所以这里会运行RuntimeInit.zygoteInit。
public class RuntimeInit { ...... public static final void zygoteInit(String[] argv) throws ZygoteInit.MethodAndArgsCaller { // TODO: Doing this here works, but it seems kind of arbitrary. Find // a better place. The goal is to set it up for applications, but not // tools like am. System.setOut(new AndroidPrintStream(Log.INFO, "System.out")); System.setErr(new AndroidPrintStream(Log.WARN, "System.err")); commonInit(); zygoteInitNative(); int curArg = 0; for ( /* curArg */ ; curArg < argv.length; curArg++) { String arg = argv[curArg]; if (arg.equals("--")) { curArg++; break; } else if (!arg.startsWith("--")) { break; } else if (arg.startsWith("--nice-name=")) { String niceName = arg.substring(arg.indexOf('=') + 1); Process.setArgV0(niceName); } } if (curArg == argv.length) { Slog.e(TAG, "Missing classname argument to RuntimeInit!"); // let the process exit return; } // Remaining arguments are passed to the start class's static main String startClass = argv[curArg++]; String[] startArgs = new String[argv.length - curArg]; System.arraycopy(argv, curArg, startArgs, 0, startArgs.length); invokeStaticMain(startClass, startArgs); } ...... }
这里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step 1中传进来的”android.app.ActivityThread”值,表示要执行android.app.ActivityThread类的main函数。
7. Zygote.invokeStaticMain
public class ZygoteInit { ...... static void invokeStaticMain(ClassLoader loader, String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = loader.loadClass(className); } catch (ClassNotFoundException ex) { ...... } Method m; try { m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { ...... } catch (SecurityException ex) { ...... } int modifiers = m.getModifiers(); ...... /* * 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. */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); } ...... }
从代码中可以看到,通过ClassLoader加载对应的android.app.ActivityThread类,然后再获取到对应的main函数句柄,最后调用该类的main函数。不过这里的调用方式比较有意思,不知直接调用,而是通过抛出一个异常。这样做的方式是为了清空堆栈,让系统认为新进程是从ActivityThread的main函数开始的。
8.ActivityThread.main
public final class ActivityThread { ...... public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>"; Slog.i(TAG, "Main thread of " + name + " is now exiting"); } ...... }
从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象,然后进入消息循环中,这样,我们以后就可以在这个进程中启动Activity或者Service了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
我正在使用Play框架1.2.5和Hibernate3.25来开发我的Web应用程序。我遇到应用程序启动问题,速度很慢:( 对于任何JavaEE servlet驱动的应用程序,我们使用来初始化会话工厂(这确实是一项耗时的工作),一旦部署了应用程序,会话工厂就会被初始化,并且所有这一切都必须在应用程序准备好为最终用户使用之前完成。这样,当用户触发第一个请求时,第一个请求的响应时间更快。 但是,对于P
本文向大家介绍android之BroadcastReceiver应用详解,包括了android之BroadcastReceiver应用详解的使用技巧和注意事项,需要的朋友参考一下 今天我们来讲一下Android中BroadcastReceiver的相关知识。 BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。 在Android系统中,广播
2.5.应用程序框架 应用程序框架是Android程序的执行环境,也是开发者的强大工具箱。另外,它也拥有Android平台中最全面最完善的文档。良好的文档可以激发广大开发人员的创意,也可以为他们构建优秀的应用程序提供有力的支持。 在应用程序框架中,你可以发现很多为Android设计的Java库。除此之外,也有系统服务的支持,比位置、传感器、WiFi、电话等等。 在后面的学习与实践中,将把我们的主要
我使用Hadoop构建了一个在分布式环境中搜索类似图像存储的应用程序。但是Hadoop不支持实时处理,这就是响应时间长的原因。我知道Storm是另一个大数据分析应用程序的框架。但是我很困惑我们是否可以使用Storm来实现这种应用程序。 有没有人建议什么样的应用程序可以有效地使用Storm框架。
如何使用appium/python/robot框架在android原生应用程序中滚动到页面底部?我尝试了以下方法,但无法使用driver.execute_脚本(“window.scrollTo(1441532)”)和driver.execute_脚本('mobile:scroll',{'duration':1,'startX':48,'startY':892,'endX':144,'endY':1
问题内容: 我正在设计和构建桌面应用程序。我正在考虑使用eclipse或netbeans作为此应用程序的基础。但是,我从未在这两个平台上构建过。我个人倾向于使用netbeans,因为它像该平台一样容易学习。但是,我想问一下实际上已经在这些平台上构建的人员,在此之前哪个更易于使用? 我对easyr的个人定义如下: 易于上手 一致的逻辑API 好的文档 易于构建和部署 非常感谢, 乔希 问题答案: 关