有关android加快开机速度
有关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加快开机速度相关推荐
- linux开发板加快开机速度,readahead加速Linux开机速度
在一两年前,Linux核心尚缺乏一个好的的硬碟预读机制时,桌面系统的使用者若要加速开机的速度,通常得先解决开机的瓶颈问题.于是得依赖如readahead这样的工具来预先载入想读入的档案,以便提高系统载 ...
- 关于Android 手机 开机速度的优化
做了这么多年的手机,从来没写过什么文章.以下只是记录下平时自己的修改,仅供参考 关于mtk 平台手机开机速度的优化 第一:尽量减少data区内置app的数量,这个会严重影响开机速度,特别是第一次的开机 ...
- 计算机win7如何加快开机速度,加快win7开机速度 让Win7系统加快开机速度小于30秒的方法...
如今使用win7系统的用户越来越多了,win7是一个比较稳定的系统,但是有一个比较不好的就是,如果没有使用SSD硬盘的时候,开机速度就会比较慢,很多人对开机速度还是很关心的,那么要怎么加快win7开机 ...
- 简单几步优化你的windows,加快开机速度(重装windows之后要做的几件事)
每个人都想要让自己的系统运行得快一些,开机快一些,我就来说说我自己的经验,我使用的系统是windows8.1,当然这有些方法也适用于其他的系统,我每次重装完系统之后第一件事就是下面几步,当然重装系统之 ...
- Win系统 - 6步加快开机速度,来比比谁更快?
在开始今日份加快开机速度的教程之前,例行公事补充基础知识--如何不借助第三方软件查看自己的开机速度? ①在运行(Win+R)中输入eventvwr打开事件查看器: ②在打开的窗口中切换到Windows ...
- win10如何加快开机速度【系统天地】
如何优化win10开机速度,虽然说Windows10系统的开机速度关闭算不上慢,但大多数的用户都追求极速的效果.那么重点来了,要怎样设置win10才能到达加快开机的速度呢?别着急,小编这就来给大家分享 ...
- w ndows xp开机时间长,xp开机速度慢|windows xp系统如何加快开机速度-系统城·电脑系统下载之家...
大家有时候在操作使用windows xp系统的过程中,会发现电脑越来越卡,每一次开机速度都很慢.为什么会出现这种情况呢?其实随着电脑的使用,电脑的开机速度或多或少的会变慢下来,一方面是电脑配置问题,另 ...
- xp系统整个计算机非常慢,xp系统开机速度慢怎么办|xp系统如何加快开机速度
即使是Windows 10已经更新了多次的今天,Windows XP仍然有着相当的地位现在市场上使用Windows XP系统的用户还是不在少数,依然有一些忠实的XP系统用户在继续使用,相信很多用户都会 ...
- windows系统加快开机速度的方法【图文教程】
在现今生活节奏快速的过程中,感觉什么都想要快上一步,所以如果你的电脑开始速度比较慢,那么如果你要在网上抢购小米的吧,那不就是比别人慢一步了!所以想要自己的电脑加快开开机速度么!那就一起来看看吧! 首先 ...
最新文章
- 欢迎使用CSDN-markdown
- 深藏不露,挖掘4种大脑网络中的管理工具
- 【渝粤教育】广东开放大学 文化项目管理 形成性考核 (36)
- MySQL笔记-Windows安装MySQL5.7
- 移动端API接口优化的术和结果
- Android FrameWork——Binder机制详解(1)
- linux能上ps吗,在linux上使用ps(转载)
- 如何在html创建js对象,在js中使用createElement创建HTML对象和元素
- 7.业务架构·应用架构·数据架构实战 --- 业务架构书
- ImageNet下载资源(2017年)
- matlab内维尔差值,基于IGS精密星历的卫星位置内插方法比较
- matlab求最值(极值)
- mysql学习心得总结
- 很多人知道外包的种种不好,但还是选择去外包,这是为什么呢?
- wireshark抓包获取好友ip,定位所在位置
- html调用rpst 源码_在web页面中播放rtsp直播数据流方法
- SLAM学习资源免费分享-转载
- java 一元 二元 三元_一元到三元关系 二元
- win7命令行设置IP地址
- Pr调色预设怎么安装?.cube格式luts预设如何导入pr?Premiere导入LUTs预设详细教程