有关android加快开机速度

我们知道,android开机速度慢,在恢复出厂设置后开机速度更慢,其中优化dex文件的过程就耗时很多。那么我们就可以尝试将优化dexopt步骤提前到编译阶段生成img文件的环节去。当然了这是一个以rom空间换取时间的策略。

可以通过在BoardConfig.mk中加入
# Enable the optimized DEX
WITH_DEXPREOPT=true
或者直接修改system.prop
# ODEX
dalvik.vm.verify-bytecode=true

然后我们探索看看android是怎么样进行这个特性的?

$grep -r "WITH_DEXPREOPT" build/
build/core/prebuilt.mk:ifeq (true,$(WITH_DEXPREOPT))
build/core/java_library.mk:ifeq (true,$(WITH_DEXPREOPT))
build/core/main.mk:  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)
build/core/main.mk:    WITH_DEXPREOPT := true
build/core/package.mk:ifeq (true,$(WITH_DEXPREOPT))
build/core/product_config.mk:    WITH_DEXPREOPT_buildbot := true

在build/core下面有个文件dex_preopt.mk,这个文件值得注意。

android真是太庞大了,其脚本之间的关系对于我这个初涉的人还是好生畏惧,值得研究。详细如下。

======================================================

build/core/main.mk

# config/product_config.make once host-based Dalvik preoptimization is
  # working.
  ifneq (true,$(DISABLE_DEXPREOPT))
  ifeq ($(HOST_OS)-$(WITH_DEXPREOPT_buildbot),linux-true)
    WITH_DEXPREOPT := true
  endif
  endif

=====================================================

build/core/package.mk

ifeq (true,$(WITH_DEXPREOPT))
ifeq (,$(TARGET_BUILD_APPS))
ifneq (,$(LOCAL_SRC_FILES))
ifndef LOCAL_DEX_PREOPT
LOCAL_DEX_PREOPT := true
endif
endif
endif
endif

=====================================================

build/core/prebuild.mk

ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
ifeq (true,$(WITH_DEXPREOPT))
ifeq (,$(TARGET_BUILD_APPS))
ifndef LOCAL_DEX_PREOPT
LOCAL_DEX_PREOPT := true
endif
endif
endif
endif

=====================================================

build/core/java_library.mk

ifeq (true,$(WITH_DEXPREOPT))
ifeq (,$(TARGET_BUILD_APPS))
ifndef LOCAL_DEX_PREOPT
LOCAL_DEX_PREOPT := true
endif
endif
endif

====================================================

build/core/product_config.mk

# Hack to make the linux build servers use dexpreopt (emulator-based
  # preoptimization). Most engineers don't use this type of target
  # ("make PRODUCT-blah-user"), so this should only tend to happen when
  # using buildbot.
  # TODO: Remove this once host Dalvik preoptimization is working.
  ifeq ($(TARGET_BUILD_VARIANT),user)
    WITH_DEXPREOPT_buildbot := true
  endif

另外补充:

1、system/app下放置系统apk;data/app下放置内置第三方apk;

2、在生成的system/app和system/framework下会生成优化后的odex文件;

3、odex占用物理空间比dex和apk文件要大,所以上述方法是计算机操作系统中典型的空间和时间互换的思想;

下面的转自:http://www.cnblogs.com/jacobchen/p/3599483.html

[Android]Dalvik的BOOTCLASSPATH和dexopt流程

BOOTCLASSPATH简介
1.BOOTCLASSPATH是Android Linux的一个环境变量,可以在adb shell下用$BOOTCLASSPATH看到。
2.BOOTCLASSPATH于/init.rc文件中export,如果没有找到的话,可以在init.rc中import的文件里找到(如import /init.environ.rc)。
3.init.rc文件存在于boot.img的ramdisk映像中。如果仅仅是修改/init.rc文件,重启后会被ramdisk恢复,所以直接修改是没有效果的。
4.boot.img是一种特殊的Android定制格式,由boot header,kernel,ramdisk以及second stage loader(可选)组成,详见android/system/core/mkbootimg/bootimg.h。

boot.img空间结构:

** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel          | n pages
** +-----------------+
** | ramdisk         | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+

典型的ramdisk文件结构:
./init.trout.rc
./default.prop
./proc
./dev
./init.rc
./init
./sys
./init.goldfish.rc
./sbin
./sbin/adbd
./system
./data

BOOTCLASSPATH的作用
以Android4.4手机的BOOTCLASSPATH为例:
export BOOTCLASSPATH /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar...
当kernel启动时1号进程init解析init.rc,将/system/framework下的jar包路径export出来。
Dalvik虚拟机在初始化过程中,会读取环境变量BOOTCLASSPATH,用于之后的类加载和优化。

Dalvik虚拟机的启动和dexopt流程
从Dalvik虚拟机的启动过程分析 一文可以知道,Zygote会在启动后创建Dalvik虚拟机实例,并进行初始化。

那我们就接着Dalvik虚拟机初始化后开始探究它是如何通过BOOTCLASSPATH来进行dex优化的:

1.1. VM initialization

android/dalvik/vm/Init.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
std::string dvmStartup(int argc, const char* const argv[],
bool ignoreUnrecognized, JNIEnv* pEnv)
{
    ...
    ALOGV("VM init args (%d):", argc);
    ...
    setCommandLineDefaults(); // ---> 读取BOOTCLASSPATH
    ...
    if (!dvmClassStartup()) { // ---> 初始化bootstrap class loader
        return "dvmClassStartup failed";
    }
}

1.2. 读取BOOTCLASSPATH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void setCommandLineDefaults()
{
    const char* envStr = getenv("CLASSPATH");
    if (envStr != NULL) {
        gDvm.classPathStr = strdup(envStr);
    } else {
        gDvm.classPathStr = strdup(".");
    }
    envStr = getenv("BOOTCLASSPATH"); // 读取到BOOTCLASSPATH环境变量<br>
    if (envStr != NULL) {
        gDvm.bootClassPathStr = strdup(envStr);
    } else {
        gDvm.bootClassPathStr = strdup(".");
    }
    ...
}

就这样,BOOTCLASSPATH的值被保存到gDvm.bootClassPathStr中。

2.1. 初始化bootstrap class loader

android/dalvik/vm/oo/Class.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool dvmClassStartup()
{
    ...
     
    /*
    * Process the bootstrap class path. This means opening the specified
    * DEX or Jar files and possibly running them through the optimizer.
    */
    assert(gDvm.bootClassPath == NULL);
    processClassPath(gDvm.bootClassPathStr, true); // 下一步
    if (gDvm.bootClassPath == NULL)
        return false;
}

2.2. 将路径、Zip文件和Dex文件的list转换到ClassPathEntry结构体当中

1
2
3
4
5
6
static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
{
    ClassPathEntry* cpe = NULL;
    ...
        if (!prepareCpe(&tmp, isBootstrap)) {}
}

2.3. 根据cpe打开文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap)
{
    ...
  
    if ((strcmp(suffix, "jar") == 0) || (strcmp(suffix, "zip") == 0) ||
    (strcmp(suffix, "apk") == 0)) {
        JarFile* pJarFile = NULL;
        /* 打开jar包,找到class.dex或jar包旁边的.odex文件 */
        if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) {
            cpe->kind = kCpeJar;
            cpe->ptr = pJarFile;
            return true;
        }
    } else if (strcmp(suffix, "dex") == 0) {
        RawDexFile* pRawDexFile = NULL;
        /* 与dvmJarFileOpen函数作用类似,是由它复制过来重构的 */
        if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0) {
            cpe->kind = kCpeDex;
            cpe->ptr = pRawDexFile;
            return true;
        }
    } else {
        ALOGE("Unknown type suffix '%s'", suffix);
    }
    ...
}

3. 打开jar包,找到class.dex或jar包旁边的.odex文件

android/dalvik/vm/JarFile.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
int dvmJarFileOpen(const char* fileName, const char* odexOutputName,
    JarFile** ppJarFile, bool isBootstrap)
{
    ...
  
    /* Even if we're not going to look at the archive, we need to
     * open it so we can stuff it into ppJarFile.
     */
    if (dexZipOpenArchive(fileName, &archive) != 0)
        goto bail;
    archiveOpen = true;
  
    /* If we fork/exec into dexopt, don't let it inherit the archive's fd.
     */
    dvmSetCloseOnExec(dexZipGetArchiveFd(&archive));
  
    /* First, look for a ".odex" alongside the jar file.  It will
     * have the same name/path except for the extension.
     */
    fd = openAlternateSuffix(fileName, "odex", O_RDONLY, &cachedName);
    if (fd >= 0) {
        ALOGV("Using alternate file (odex) for %s ...", fileName);
        /* 读、验证header和dependencies */
        if (!dvmCheckOptHeaderAndDependencies(fd, false, 0, 0, true, true)) {
            ALOGE("%s odex has stale dependencies", fileName);
            free(cachedName);
            cachedName = NULL;
            close(fd);
            fd = -1;
            goto tryArchive;
        } else {
            ALOGV("%s odex has good dependencies", fileName);
            //TODO: make sure that the .odex actually corresponds
            //      to the classes.dex inside the archive (if present).
            //      For typical use there will be no classes.dex.
        }
    } else {
        ZipEntry entry;
  
tryArchive:
        /*
         * Pre-created .odex absent or stale.  Look inside the jar for a
         * "classes.dex".
         */
        ...
}

4.读、验证opt的header,读、验证dependencies

android/dalvik/vm/analysis/DexPrepare.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen,
u4 crc, bool expectVerify, bool expectOpt)
{
     ...
    /*
     * Verify dependencies on other cached DEX files.  It must match
     * exactly with what is currently defined in the bootclasspath.
     */
    ClassPathEntry* cpe;
    u4 numDeps;
    numDeps = read4LE(&ptr);
    ALOGV("+++ DexOpt: numDeps = %d", numDeps);
    for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
        const char* cacheFileName =
            dvmPathToAbsolutePortion(getCacheFileName(cpe));
        assert(cacheFileName != NULL); /* guaranteed by Class.c */
        const u1* signature = getSignature(cpe);
        size_t len = strlen(cacheFileName) +1;
        u4 storedStrLen;
        if (numDeps == 0) {
            /* more entries in bootclasspath than in deps list */
            ALOGI("DexOpt: not all deps represented");
            goto bail;
        }
        storedStrLen = read4LE(&ptr);
        if (len != storedStrLen ||
            strcmp(cacheFileName, (const char*) ptr) != 0)
        {
            ALOGI("DexOpt: mismatch dep name: '%s' vs. '%s'",
                cacheFileName, ptr);
            goto bail;
        }
        ptr += storedStrLen;
        if (memcmp(signature, ptr, kSHA1DigestLen) != 0) {
            ALOGI("DexOpt: mismatch dep signature for '%s'", cacheFileName);
            goto bail;
        }
        ptr += kSHA1DigestLen;
        ALOGV("DexOpt: dep match on '%s'", cacheFileName);
        numDeps--;
    }
    if (numDeps != 0) {
        /* more entries in deps list than in classpath */
        ALOGI("DexOpt: Some deps went away");
        goto bail;
    }
    ...
}

实际应用
打通了Dalvik dexopt的这个流程,那这到底又有什么用呢?
让我们看看实际开发过程中的手机升级binary后无法boot到Home界面的log:

 1 AndroidRuntime >>>>>> AndroidRuntime START com.android.internal.os.ZygoteInit <<<<<<
 2 AndroidRuntime CheckJNI is ON
 3 dalvikvm DexOpt: Some deps went away
 4 dalvikvm /system/framework/core-junit.jar odex has stale dependencies
 5 dalvikvm DexOpt: --- BEGIN 'core-junit.jar' (bootstrap=1) ---
 6 dalvikvm DexOpt: load 42ms, verify+opt 25ms, 143956 bytes
 7 dalvikvm DexOpt: --- END 'core-junit.jar' (success) ---
 8 dalvikvm DEX prep '/system/framework/core-junit.jar': unzip in 1ms, rewrite 126ms
 9 dalvikvm DexOpt: mismatch dep name: '/data/dalvik-cache/system@framework@core-junit.jar@classes.dex' vs. '/system/framework/conscrypt.odex'
10 dalvikvm /system/framework/bouncycastle.jar odex has stale dependencies
11 dalvikvm DexOpt: --- BEGIN 'bouncycastle.jar' (bootstrap=1) ---
12 dalvikvm DexOpt: Some deps went away
13 dalvikvm /system/framework/core-junit.jar odex has stale dependencies
14 dalvikvm DexOpt: load 33ms, verify+opt 350ms, 681812 bytes
15 dalvikvm DexOpt: --- END 'bouncycastle.jar' (success) ---
16 dalvikvm DEX prep '/system/framework/bouncycastle.jar': unzip in 57ms, rewrite 548ms
17 dalvikvm DexOpt: mismatch dep name: '/data/dalvik-cache/system@framework@core-junit.jar@classes.dex' vs. '/system/framework/conscrypt.odex'
18 dalvikvm /system/framework/ext.jar odex has stale dependencies
19 dalvikvm DexOpt: --- BEGIN 'ext.jar' (bootstrap=1) ---
20 dalvikvm DexOpt: Some deps went away
21 dalvikvm /system/framework/core-junit.jar odex has stale dependencies
22 dalvikvm DexOpt: mismatch dep name: '/data/dalvik-cache/system@framework@core-junit.jar@classes.dex' vs. '/system/framework/conscrypt.odex'
23 dalvikvm /system/framework/bouncycastle.jar odex has stale dependencies

根据前面的流程,结合log我们就可以分析出,DexOpt: mismatch dep name: '/data/dalvik-cache/system@framework@core-junit.jar@classes.dex' vs. '/system/framework/conscrypt.odex'是错误所在,是由于data/dalvik-cache/下的dex cache文件和system/framework/下的jar文件验证依赖关系时候对应不上。

从函数dvmCheckOptHeaderAndDependencies()可以得知,BOOTCLASSPATH和cache必须是完全一致的
尝试删除所有cache文件,重启还是不行。那么应该想到BOOTCLASSPATH和实际的system/framework/的jar包不一致,才会导致和其生成的cache不一致。
对比一下果然不一致,issue trouble-shooted.

解决方法:把对应boot.img也烧进去,这样BOOTCLASSPATH就能更新一致,dex优化就能正确进行下去。

有关android加快开机速度相关推荐

  1. linux开发板加快开机速度,readahead加速Linux开机速度

    在一两年前,Linux核心尚缺乏一个好的的硬碟预读机制时,桌面系统的使用者若要加速开机的速度,通常得先解决开机的瓶颈问题.于是得依赖如readahead这样的工具来预先载入想读入的档案,以便提高系统载 ...

  2. 关于Android 手机 开机速度的优化

    做了这么多年的手机,从来没写过什么文章.以下只是记录下平时自己的修改,仅供参考 关于mtk 平台手机开机速度的优化 第一:尽量减少data区内置app的数量,这个会严重影响开机速度,特别是第一次的开机 ...

  3. 计算机win7如何加快开机速度,加快win7开机速度 让Win7系统加快开机速度小于30秒的方法...

    如今使用win7系统的用户越来越多了,win7是一个比较稳定的系统,但是有一个比较不好的就是,如果没有使用SSD硬盘的时候,开机速度就会比较慢,很多人对开机速度还是很关心的,那么要怎么加快win7开机 ...

  4. 简单几步优化你的windows,加快开机速度(重装windows之后要做的几件事)

    每个人都想要让自己的系统运行得快一些,开机快一些,我就来说说我自己的经验,我使用的系统是windows8.1,当然这有些方法也适用于其他的系统,我每次重装完系统之后第一件事就是下面几步,当然重装系统之 ...

  5. Win系统 - 6步加快开机速度,来比比谁更快?

    在开始今日份加快开机速度的教程之前,例行公事补充基础知识--如何不借助第三方软件查看自己的开机速度? ①在运行(Win+R)中输入eventvwr打开事件查看器: ②在打开的窗口中切换到Windows ...

  6. win10如何加快开机速度【系统天地】

    如何优化win10开机速度,虽然说Windows10系统的开机速度关闭算不上慢,但大多数的用户都追求极速的效果.那么重点来了,要怎样设置win10才能到达加快开机的速度呢?别着急,小编这就来给大家分享 ...

  7. w ndows xp开机时间长,xp开机速度慢|windows xp系统如何加快开机速度-系统城·电脑系统下载之家...

    大家有时候在操作使用windows xp系统的过程中,会发现电脑越来越卡,每一次开机速度都很慢.为什么会出现这种情况呢?其实随着电脑的使用,电脑的开机速度或多或少的会变慢下来,一方面是电脑配置问题,另 ...

  8. xp系统整个计算机非常慢,xp系统开机速度慢怎么办|xp系统如何加快开机速度

    即使是Windows 10已经更新了多次的今天,Windows XP仍然有着相当的地位现在市场上使用Windows XP系统的用户还是不在少数,依然有一些忠实的XP系统用户在继续使用,相信很多用户都会 ...

  9. windows系统加快开机速度的方法【图文教程】

    在现今生活节奏快速的过程中,感觉什么都想要快上一步,所以如果你的电脑开始速度比较慢,那么如果你要在网上抢购小米的吧,那不就是比别人慢一步了!所以想要自己的电脑加快开开机速度么!那就一起来看看吧! 首先 ...

最新文章

  1. 欢迎使用CSDN-markdown
  2. 深藏不露,挖掘4种大脑网络中的管理工具
  3. 【渝粤教育】广东开放大学 文化项目管理 形成性考核 (36)
  4. MySQL笔记-Windows安装MySQL5.7
  5. 移动端API接口优化的术和结果
  6. Android FrameWork——Binder机制详解(1)
  7. linux能上ps吗,在linux上使用ps(转载)
  8. 如何在html创建js对象,在js中使用createElement创建HTML对象和元素
  9. 7.业务架构·应用架构·数据架构实战 --- 业务架构书
  10. ImageNet下载资源(2017年)
  11. matlab内维尔差值,基于IGS精密星历的卫星位置内插方法比较
  12. matlab求最值(极值)
  13. mysql学习心得总结
  14. 很多人知道外包的种种不好,但还是选择去外包,这是为什么呢?
  15. wireshark抓包获取好友ip,定位所在位置
  16. html调用rpst 源码_在web页面中播放rtsp直播数据流方法
  17. SLAM学习资源免费分享-转载
  18. java 一元 二元 三元_一元到三元关系 二元
  19. win7命令行设置IP地址
  20. Pr调色预设怎么安装?.cube格式luts预设如何导入pr?Premiere导入LUTs预设详细教程

热门文章

  1. linux卸载java rpm_Linux卸载jdk、rpm命令、rm命令参数方法
  2. 网上炒作的哪些日赚千元不是梦的手机赚钱项目是真的吗
  3. Qt中解除按键在聚焦时键盘空格键可以控制
  4. 网络安全应急响应具体操作流程
  5. android 自己调用系统相机保存的照片存到自定义文件夹里面用电脑看该照片显示0KB或者是无法查看?或者说用手机助手导出照片导出失败?
  6. EXCEL 对数据分列
  7. QCY T1s 双耳配对教程
  8. 【存储器】中国大陆主要SSD主控芯片厂商盘点
  9. 深度解析ILCC:区块链技术如何改善制造业?
  10. 车企小程序,汽车行业新战场【产品分析报告】