Android packaging related knowledge sorting (A)

Sort out some knowledge points related to Android packaging, including some basic concepts, APK packaging, installation process.

JVM Dalvik ART

JVM & DVM

DVM, also known as Dalvik, is a Java VIRTUAL machine developed by Google for the Android platform, while JVM is a traditional Java virtual machine, which has many specific versions and is cross-platform. So their differences are mainly reflected in the following points:

  1. Architecturally, the JVM is stack-based and the DVM is register-based.
  2. What the JVM executes is compiled from Java files.classFile, while DVM performs Java file compilation to.classAfter the file is compiled again.dexFile.
  3. The JVM can only run one instance, with several applications in the same virtual machine. DVM can run multiple virtual machine instances, with each app running in a separate virtual machine process.

DVM & ART

ART, or Android Runtime, is also an updated version of the Dalvik VIRTUAL machine. Since Android 4.4, ART has been built into the system until 5.0, when Dalvik was completely replaced with ART. The APP installed by Dalvik dynamically interprets part of the bytecode to machine code during running, which is just-in-time compilation (JIT), while ART converts the bytecode to machine code and stores the corresponding storage space at the beginning of app installation. This process is pre-compilation. AOT (Ahead of time). Therefore, APP under DVM runs slowly and frequently accesses CPU, while app under ART takes longer installation time and occupies more space, but the startup and running speed is improved and power consumption is saved.

JIT & AOT

As mentioned earlier, JIT and AOT are just two different forms of compilation, one even if compiled and the other ahead of time compiled. JIT was introduced from Android 2.2. The virtual machine executes the bytecode DEX, but the machine executes the machine code. Therefore, every time a program is run, the DEX needs to be converted to the local machine code and handed over to the machine for execution. When JIT is added, this process is handled by the JIT. To be specific, every time a program encounters a new class, it will compile the class and convert the compiled result into a simplified native instruction code, so that the next time the same logic is executed, it will execute the simplified native instruction code directly, which will increase the speed of the operation. But if you JIT all the classes, then the ones that are executed less often will slow down the whole thing because it takes time for you to transform. So not all code is JIT, it’s selective. In addition, JIT is not a one-size-fits-all process; it has to be re-jit at every run. AOT, by contrast, is “space for time”. Bytecode is converted to machine code and stored in a specific storage space on the first installation. This is slower to install and takes up extra storage space, but the benefit is obvious, as the program simply executes the machine code at run time and runs faster. Both JIT and AOT have their advantages and disadvantages. So Google combined JIT and AOT in Android 7.0. Specifically, applications will no longer compile ahead of time when they are first installed, so installation speed will not slow down. When the application runs, it is JIT optimized and stored in the JIT code cache, and the functions that are executed more frequently are marked and recorded in a profile. Once the phone is in a charging and idle state, the system scans these profiles at regular intervals and executes AOT. It is thought that only those hot functions are optimized, so there is no significant change in the first run, and after many runs, there is a significant speed increase. It also takes up less extra storage and is faster to install.

DEX ODEX OAT

The JVM executes a.class file compiled from a class file, while the Android VIRTUAL machine executes a.class file further processed by a.class file, called dx, resulting in a.dex file. So the DEX file is simply a.class file that is converted by the dx tool. Typically, a project with many class files will generate many.class files, and these.class files will be optimized through the file content, and then merged, resulting in a.dex file (in the case of 64K not being considered). The ODEX file, namely, Optimized dex, is a file Optimized after the dex. It is not a file format, that is, there is no. Odex suffix, it is a type, that is, DEX file optimized file type. So, in particular, a.dex file that’s been optimized might still have a.dex suffix, or it might have a new.oat suffix, but they’re still ODEX files — optimized dex files. Specifically, after our APP is packaged into APK, APK, as a compressed file, contains the DEX file. When the system is powered on for the first time, the apK file is decompressed, the DEX file is extracted, and stored in the data/app directory of the system. Then, the important point is that if the Dalvik VM is currently running, the DEX file will be optimized by the Dalvik VM. This optimization is performed through the function dexopt, and the file name generated by the optimization is still the old file name and the suffix is still. DEX, but it is no longer a DEX file. It’s an optimized DEX file, which is an ODEX file. If the virtual machine running in the current system is ART, the DEX file will also be optimized by the ART VIRTUAL machine. This optimization is performed using dex2OAT tool, and the generated file name is still the old file name, with the suffix changed to. Oat, and the file type changed to ODEX. In both optimization methods, ODEX files will eventually be stored in the data/ Dalvik-cache directory of the system. Why do you do this with file names? Since the virtual machine is transferred from Dalvik to ART, the optimized file name and path remain unchanged, so any code that references ODEX files by absolute path need not be modified.

apk

The content of the apk

Analyze the packaging process by first looking at the results of the packaging and then working backwards to see how each piece was packaged.

Apk is the full name of Android Package, which is actually a compressed file with a suffix of. Apk, which contains all the data of codes and resources contained in Android App. After decompressing an APK package with the decompression tool, you can see the following directory:

  1. AndroidManifest.xml

This file is a manifest file for Android apps, and it’s the one we deal with when we write apps. This file contains all interfaces, permissions, BroadCast, and information about the application program. This file is used by the application program to introduce itself to the system. 2. The assets directory stores static resource files in APK. You need to access the content through the AssetManager class. 3. Classes.dex The code in the Android project generates a.class file when compiled, which is then converted into bytecode files using the dx tool, which is the dex file. Normally there is only one classes.dex, and if the project code has more than 65535 methods and uses multidex, there will be other. Dex files. 4. Meta-inf The meta-INF directory contains application signature information, which is used to verify the integrity and validity of THE APK file and help the system ensure that the APK file is complete and secure and not damaged or modified during application installation. 5. The res directory houses all other resources, including layout resources, drawable resources, etc. These resources are mapped to resource ids. Applications access these resource files through the index of the resource. 6. Resources. Arsc Resources are indexed by resource IDS. Here, resources.arsc is a resource index table that records the resource file path and its corresponding ID, while r.java file defines the ID associated with the resource. In the program, obtain the resource ID through the resource name defined by R file, and then use the resource ID to obtain the specific path of the resource in resources.arsc.

Apk packaging process

Here’s the latest packaging flowchart from the official website:

Here’s the packaging flowchart from the old website:



The old version was a little more detailed. Take the old version of packaging flow chart, packaging mainly has the following steps:

  1. Use the AAPT tool to process all the resources, generating an R.Java file, a resources.arsc file, and other resources.

  2. Process the. Aidl file and generate the corresponding Java interface file.

  3. R.java file, Java interface file, Andorid source code, compiled through the Java compiler to get the Java bytecode file. Class file.

  4. Get the dependent third-party library file and generate the.dex file with the.class file obtained in the previous step by using the dx tool.

  5. Arsc resource index file, res resource directory, and the.dex file obtained in the previous step, using the apkBuilder tool to build the initial.apk file.

  6. Use the Jarsigner tool to sign the. Apk file.

  7. Use the zipalign tool to align.apk files. (Speed up resource access by aligning resources with four-byte boundaries)

After the above seven steps, a finished APK file is born.

Apk installation process

The installation of Android applications involves the following directories:

  • /data/app: stores APK files
  • /data/data: stores application data
  • /data/dalvik-cache: stores ODEX files

The installation process is as follows:

  1. Copy the APK file to the /data/app directory on the system.
  2. Decompress the APK file.
  3. Verify the signature and verify the validity and security of THE APK package by using the signature file in the APK file.
  4. Decompress and verify the. Dex file.
  5. The decompressed. Dex file is optimized to generate odex file and stored in /data/dalvik-cache.
  6. In the /data/data directory, create a directory with the package name of the application to store all data for the application.