AppZygote是什么?

众所周知,app进程、SystemServer进程都是由Zygote进程孵化的,最近梳理这块逻辑的时候,无意中发现了一个叫AppZygote和一个叫AppZygoteInit的java类,挺新鲜的,先看看源码开头对AppZygote的定义吧:

AppZygote is responsible for interfacing with an application-specific zygote. Application zygotes can pre-load app-specific code and data, and this interface can be used to spawn isolated services from such an application zygote. Note that we'll have only one instance of this per application / uid combination.

大概翻译一下:

AppZygote 负责与指定app的zygote进行对接。应用程序的Zygote可以预加载app指定的代码和数据,还可以从该接口派生独立的服务。请注意,对于每个application/uid组合,我们只有一个实例。

那接着看看AppZygoteInit的注释说明吧:

Startup class for an Application zygote process. See ZygoteInit for generic zygote startup documentation.

同样附上翻译

应用程序Zygote进程的启动类。参见ZygoteInit了解zygote启动的文档。

看完一头雾水,有种“听君一席话,胜似听君一席话”的感觉。那赶紧百度,必应一把,哦豁,什么都没搜到,不合理啊,那还是看源码吧。

class AppZygoteInit {
    //自定义了一个ZygoteServer,跟Zygote一样,可以接收socket访问来fork 新的app进程
    private static class AppZygoteServer extends ZygoteServer {
		  @Override
        protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
                throws IOException {
            //重写createNewConnection 方法,返回一个自定义个connection对象。
            return new AppZygoteConnection(socket, abiList);
        }
    }
    //自定义ZygoteConnection
    private static class AppZygoteConnection extends ZygoteConnection {
         @Override
        protected void handlePreloadApp(ApplicationInfo appInfo) {
            //1. 通过ApplicationInfo 构建LoadedApk
            LoadedApk loadedApk = new LoadedApk(null, appInfo, null, null, false, true, false);
            //2. 获取 LoadedApk的ClassLoader,后面反射ZygotePreload的实例要用
            ClassLoader loader = loadedApk.getClassLoader();
            //用来定义一个应用程序的组件,通过调用Intent中的setComponent方法,可以打开本应用或者其他应用中的组件,如:Activity和Service
            ComponentName preloadName = ComponentName.createRelative(appInfo.packageName,
            appInfo.zygotePreloadName);
            //3. 反射获取ZygotePreload的Class对象
            Class<?> cl = Class.forName(preloadName.getClassName(), true, loader);
            //4. 反射获取ZygotePreload的构造方法
            Constructor<?> ctor = cl.getConstructor();
            //5. 创建ZygotePreload的具体实例对象
            ZygotePreload preloadObject = (ZygotePreload) ctor.newInstance();
            //6. 调用 ZygotePreload的doPreload开始预加载资源。
            preloadObject.doPreload(appInfo);
            //7. 向socket的输出流写入preload的结果
            DataOutputStream socketOut = getSocketOutputStream();
            socketOut.writeInt(loader != null ? 1 : 0);
            Log.i(TAG, "Application preload done");
        }
    }
    //看到没,main方法,说明AppZygote运行在一个独立的进程中
    public static void main(String[] argv) {
        AppZygoteServer server = new AppZygoteServer();
        //启动一个socket server
        ChildZygoteInit.runZygoteServer(server, argv);
    }
}

再看看ZygotePreload,它是一个接口:

/**
 * 这个接口被AndroidManifest.xml中<application>标签下android:zygoteReloadName指定的class来实现。它负责预加载应用程序代码和数据,这些代码和数据将由所有在<service>标签下将android:useAppZygote属性设置为true的独立服务共享。请注意,此类的实现必须提供一个不带参数的默认构造函数。
 */
public interface ZygotePreload {
    /**
     每次启动应用程序 Zygote 时都会调用此方法一次。它通常在使用它的独立服务首次启动时启动。在所有使用它的独立服务停止时停止。
     */
    void doPreload(@NonNull ApplicationInfo appInfo);
}

ZygotePreload 用于提前预加载特定资源。它有以下实现类:

  1. WebViewZygotePreload: WebView 组件的预加载实现类。它负责预加载 WebView 相关的资源,包括 JavaScript 引擎、Web 内容渲染引擎等。
  2. GraphicsEnvironmentZygotePreload:用于预加载图形环境相关资源。例如 Skia 图形库、OpenGL ES 等。
  3. FontZygotePreload:用于预加载字体资源。

AppZygoteandroid8.0引入,跟Zygote一样,也是一个系统进程,跟外界也是通过socket通信。不过AppZygote只为fork app进程服务,不像Zygote还要负责fork其他进程,(比如SystemServer)。AppZygote的功能相对单一,用于加速app进程的启动。这个处理有点像AMS(ActivityManagerService)把对Activity的管理单独提取到ATMS(ActivityTaskManagerService)中一样。

AppZygote的作用是:起到优化应用程序启动运行的作用,怎么做到的呢?

  1. AppZygote会预加载一些常见的系统类资源,而被fork出的子进程会拥有父进程的全部代码和状态,也就是拥有父进程的功能。这样在每次开启新的app进程时就不需要重新加载一遍,从而减少app进程启动时间。
  • 系统类:如图形渲染、网络通信等。
  • 系统级服务:如,位置服务、通知管理等。
  1. AppZygote也会预加载和初始化一些常用的应用程序组件资源,并将它们缓存起来。当应用程序需要启动时,达到减少内存消耗的目的。
  • 应用级共享组件:如Activity、Service等
  • 应用级共享资源:如布局文件、字符串资源等。
  1. 支持进程的快速复用:如果一个应用程序的进程在前台和后台之间频繁切换,AppZygote可以保持该进程的虚拟机实例的状态,当下次需要启动该应用程序时,可以快速复用这个虚拟机实例,从而减少启动时间和内存消耗。

它通过共享系统类和资源、提供隔离的虚拟机实例等机制,减少了启动时间和内存消耗,提高了系统的性能和稳定性。

你可能感兴趣的:(android,zygote)