首次重启时,较新的Android版本会进行哪些应用程序优化?


28

我收到了来自电信运营商Vodafone IT的Nexus S官方OTA Google对Nexus S的Android Ice Cream Sandwich 4.0.4的官方更新。更新后首次自动重启时,系统显示一条通知,指出它正在优化已安装的应用程序。第一次重新启动时,Android 4.0+会进行哪种优化?

Answers:


40

探究grepCode上PackageManagerService类(警告:此类文件很大,浏览器渲染时可能会碰到很多),优化消息显示在以下上下文中:

public void performBootDexOpt() {
    ArrayList<PackageParser.Package> pkgs = null;
    synchronized (mPackages) {
        if (mDeferredDexOpt.size() > 0) {
            pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
            mDeferredDexOpt.clear();
        }
    }
    if (pkgs != null) {
        for (int i=0; i<pkgs.size(); i++) {
            if (!isFirstBoot()) {
                try {
                    ActivityManagerNative.getDefault().showBootMessage(
                            mContext.getResources().getString(
                                    com.android.internal.R.string.android_upgrading_apk,
                                    i+1, pkgs.size()), true);
                } catch (RemoteException e) {
                }
            }
            PackageParser.Package p = pkgs.get(i);
            synchronized (mInstallLock) {
                if (!p.mDidDexOpt) {
                    performDexOptLI(p, false, false);
                }
            }
        }
    }
}


此处的值com.android.internal.R.string.android_upgrading_apk是字符串“优化应用程序”。用外行的话讲,它循环遍历设备上的每个应用程序,通过先调用showBootMessage()然后performDexOptLI()在应用程序上调用来更新屏幕上的消息。很自然,下一个问题是“做performDexOptLI()什么?” 看起来像这样:

private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
    boolean performed = false;
    if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
        String path = pkg.mScanPath;
        int ret = 0;
        try {
            if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
                if (!forceDex && defer) {
                    mDeferredDexOpt.add(pkg);
                    return DEX_OPT_DEFERRED;
                } else {
                    Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
                    ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
                            !isForwardLocked(pkg));
                    pkg.mDidDexOpt = true;
                    performed = true;
                }
            }
        } catch (...) {
           //I've trimmed out a bunch of exception handling here, it basically just writes to
           //the log and sets the return value
        }
    }

    return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
}

因此,这会dexopt在需要它的所有应用程序上调用该实用程序。很难找到任何有关的简单文档dexopt,但是这里有一个高层次的概述。可以这么说,即时(JIT)编译器正在使用它来创建优化的.dex文件,以帮助提高设备上应用程序的性能,并将其输出到VM缓存中。它将.dex文件存储在缓存中的原因是,否则它将在您想要运行应用程序的任何时间重新提取它们(.apk只是一个存档,不是可执行文件!)。因此,将它们保留在/data/dalvik-cache目录中以重用它们是有意义的,并dexopt在初始提取过程中对其进行一些优化。


TL; DR(或非程序员摘要,我想):它正在重建Dalvik缓存。


这确实是系统通过所有已安装的应用程序时看到的消息。感谢您的出色回答。
Paolo Amoroso 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.