Android应用管理四 -- APK包的安装、卸载和优化(PackageManagerService)

本文介绍了Android应用管理中的ODEX(Optimized DEX)优化,涉及ODEX的作用、dalvik-cache解释、开机速度提升及源码解析。探讨了在编译时进行ODEX优化以减少首次开机时间,并详细阐述了PackageManagerService在初始化过程中的dexopt操作。
摘要由CSDN通过智能技术生成

ODEX简介

什么是ODEX?

    如果你的apk文件或者jar包没有做过odex优化的话,打开你的文件,你一定会找到一个名字叫做classes.dex的文件(通常情况下,我们看到的实际上是一个以.apk为后缀名的压缩文件,classes.dex文件包含在压缩文件中),这个就是我们的java源码经过ADT编译之后转换成的可执行文件。

    对于使用Dalvik虚拟机的Android版本,当系统第一次启动时,会对.apk/.jar文件里的classes.dex文件进行一次“翻译”,“翻译”的过程也就是守护进程installd的函数dexopt来对dex字节码进行优化,实际上也就是将它转化为.odex文件,最终odex文件被保存在手机的VM缓存目录/data/dalvik-cache下(注意这里.odex文件名字仍是.dex后缀,格式如:system@priv-app@Settings@Settings.apk@classes.dex)。

    对于使用ART虚拟机的Android版本,首次进系统时,调用/system/bin/dexopt工具来将.apk/.jar里的classes.dex文件翻译成本地机器码,同样保存在/data/dalvik-cache下。

    无论是dalvik里对classes.dex进行优化,还是art里对classes.dex进行翻译成本地机器码,最终得到的结果都保存在相同名称的odex文件里,但是前者实际是一个dey文件(表示优化过的dex文件),而后者是一个oat文件(实际上是自定义的elf文件,里面全是机器码)。简单来说,无论是DVM,还是ART,优化的结果都是一个odex文件,只是这两种odex文件有着本质区别(一个是dey字节码,一个是oat机器码)。之所以这么设计,主要通过这种方式,原来任何通过绝对路径引用了该odex文件的代码就都不需要修改了,可以理解为这是ART与Dalvik兼容的结果。所以首次开机时,启动比较慢,就是因为系统在做这些事情,预置的APK越多,启动时间就越长。

    如果将这件事情,在编译系统时就做好,装到image里去,那么首次开机的时间,就会节约很多,不过这样做也会让生成的image变得比以前大。

什么是dalvik-cache?

    当Android启动时,DVM监控所有程序(APK文件)和框架,并且为他们创建一个依存关系树。DVM通过这个依存关系树来为每个程序优化代码并存储在Dalvik缓存中。这样,所有程序在运行时都会使用优化过的代码。这就是当你刷一个新ROM时,有时候第一次启动时间非常长的原因。当一个程序(或框架库)发生变更,DVM将会重新优化代码并且再次将其保存在缓存中。

    /cache/dalvik-cache存放的是system上的程序生成的dex文件,/data/dalvik-cache存放的是/data/app生成的dex文件。

ODEX优化有什么用?

    ODEX的用途是分离程序资源和可执行文件、以及做预编译处理,达到加快软件加载速度和开机速度的目的。一般来说,厂商的原厂系统都会为自己的ROM做ODEX优化处理以提高性能。

    很多人都会疑问,Android5.0开始,默认已经使用ART虚拟机,弃用Dalvik了。应用程序会在安装时被编译成OAT文件(ART上运行的格式),ODEX还有什么用呢?这里我们先看下Google的回答:

Dex file compilation uses a tool called dex2oat and takes more time than dexopt.
The increase in time varies, but 2-3x increases in compile time are not unusual.
For example, apps that typically take a second to install using dexopt might take 2-3 seconds.

    DEX转换成OAT的这个过程是5.0以上系统用户在安装程序或是刷入ROM、增量更新后首次启动时必然执行的。按照Google的说法,相比做过ODEX优化,没有做过优化的DEX转换成OAT需要花费更长的事件,一般是2-3倍。比如安装一个ODEX优化过的程序假设需要1秒钟,未做过优化的程序就需要2~3秒。

    由此可见,虽然Dalvik被弃用了,但ODEX优化在Android5.0系统以上依旧起着作用。

编译时ODEX 相关变量

    这里简单介绍一下Android编译时,odex优化相关的一些编译选项,可以针对自己的的需要,设置自己系统的这些编译选项,以达到不同的目的。

  • WITH_DEXPREOPT

    这个变量相当于编译时odex优化的总开关,只要想在编译时生成odex文件,就必须设置为true。开启该参数后,会对APK、JAR以及内核镜像进行优化。其中,针对APK、JAR的最直观的优化体现就是,程序的dex被转换成odex。

    不过这里需要注意的是打开WITH_DEXPREOPT 宏之后,预编译时提取Odex会增加一定的空间,预置太多apk,会导致system.img 过大,而编译不过。遇到这种情况可以通过删除apk中的dex文件、调大system.img的大小限制,或在预编译时跳过一些apk的odex提取。

  • WITH_DEXPREOPT_BOOT_IMG_ONLY

    在WITH_DEXPREOPT:=true的情况下,若同时设置WITH_DEXPREOPT_BOOT_IMG_ONLY为true,则编译时只对PRODUCT_BOOT_JARS变量里定义的jar包进行odex优化,生成boot.oat和boot.art。

  • DONT_DEXPREOPT_PREBUILTS

    打开这个变量后,编译时不会对Android.mk中包含了include$(BUILD_PREBUILT)的Apk进行odex优化。对于一些以后需要自升级的apk这样做,可以节省空间。

  • LOCAL_DEX_PREOPT

    可在各个Android.mk文件里单独设置这个变量,它只会影响当前Android.mk编译的单个jar包或者apk文件。当设置为true时,classes.dex文件将从.apk/.jar文件中删除;设置成
nostripping,classes.dex文件仍保留在.apk/.jar文件里。

  • DEX_PREOPT_DEFAULT

    当WITH_DEXPREOPT:=true时,LOCAL_DEX_PREOPT如果没有进行单独设置,那么它的值就是DEX_PREOPT_DEFAULT,所以可以通过设置DEX_PREOPT_DEFAULT的值,统一改变所有的LOCAL_DEX_PREOPT的默认值。

    一个常见的场景是,DEX_PREOPT_DEFAULT:=nostripping,导致最后生成的image里同时存在classes.dex和.odex文件,造成空间浪费。

ODEX优化提高首次开机速度

    现在Android手机都需要预装很多应用,这些应用的APK主要在/system/app,/system/priv-app/,/system/vendor/app等目录下。如果没有做ODEX优化,在首次开机时,SystemService.java会调用PackageManagerService对这几个目录下的APK做dexopt的优化,生成oat文件。APK越多,首次开机的事件就会越长。首次开机时,通常在手机上看到“正在优化第*个应用,总共*个应用”,这就是在对APK做dexopt的优化。

    如果我们要提高首次开机的速度,可以做如下设置:

    1、 在工程代码/device/qcom/项目名/BoardConfig.mk修改两个设置

        修改下面两个设置,在编译时,对jar、APK都做ODEX优化,生成对应的ODEX文件:

        DISABLE_DEXPREOPT := false
        WITH_DEXPREOPT := true

    如果不想在编译时做ODEX优化,可以注释掉这两行,或者把这两个值设置成:

       注释: 

        #DISABLE_DEXPREOPT := false
        #WITH_DEXPREOPT := true

       或:

       DISABLE_DEXPREOPT := true
       WITH_DEXPREOPT := false

    2、 如果设置了:

        DISABLE_DEXPREOPT := false
        WITH_DEXPREOPT := true

    在编译的时候,/system/framework/目录下面的jar包,和/system/app,/system/priv-app/,/system/vendor/app等目录下的apk文件,都会在编译时做ODEX优化。

    如果不想jar包做ODEX优化,可以在/build/core/java_library.mk文件中设置:

        LOCAL_DEX_PREOPT := false

    这样在编译时,jar包就不会做ODEX优化。

    3、 在实际开发中,有些apk如果做了ODEX优化,可能会出问题,可以通过在apk的编译目录Android.mk文件中添加:

       LOCAL_DEX_PREOPT := false

    这样该apk就不会做ODEX优化。

    如果jar包和apk都做ODEX优化,在项目中,原来首次开机速度3分钟左右可以提高到1分种左右。

源码解惑

PackageManagerService初始化

    在PackageManagerService初始化过程中,安装应用的时,PKMS都会通过另一个类Installer的方法dexopt()来对APK里面的dex字节码进行优化:

                        try {
                  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android PackageManagerserviceAndroid 系统中的一个服务,它负责管理应用程序PackageManagerservice 提供了许多功能,安装卸载、更新和管理应用程序的权限等。下面对其功能进行详细解释: 1. 安装应用程序:PackageManagerservice 能够将应用程序的 APK 文件安装到设备中。当用户从 Google Play 商店或其他渠道下载应用程序时,PackageManagerservice应用程序文件正确安装到手机的存储区域中。 2. 卸载应用程序:PackageManagerservice 可以卸载设备上的应用程序。当用户要卸载一个应用程序时,PackageManagerservice 会检查该应用程序的名及其相关文件,并将其从设备中删除。 3. 更新应用程序:PackageManagerservice 能够更新已经安装在设备上的应用程序。当用户从应用商店下载一个已经安装应用程序的更新时,PackageManagerservice 将下载的新版本进行安装,以替换旧版本。 4. 管理应用程序权限:PackageManagerservice 配合 Android 系统的权限系统,控制应用程序的权限。用户给予应用程序某些权限后,PackageManagerservice 会验证和授权应用程序的权限使用,确保应用程序的安全性和隐私保护。 除此之外,PackageManagerservice 还负责处理应用程序的签名验证、计算应用程序的版本号和版本名、管理应用程序的组件(如活动、服务等),以及处理应用程序之间的相互调用等。 总之,Android PackageManagerserviceAndroid 系统中的一个重要服务,负责管理应用程序的安装卸载、更新和权限管理等功能。它的存在确保了 Android 应用生态的安全和稳定运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值