APK compilation process - DEX file

Keywords: xml Android Java SDK

APK compilation process - DEX file

What is a DEX file?

As we know, although our applications are usually written in java, it is not Java bytecode that is ultimately executed by the Dalivk virtual machine, but dalivk bytecode.

Class bytecode is compiled into class file, and dalivk bytecode is optimized and merged into dex file. dex is an executable file that can be interpreted and executed directly by Dalvik virtual machine.

The components of Dex file content can be referenced from Android's Official Documents.

Compiling process of DEX file

Generate Dex files

1. Generating class files using javac commands

/**
 * Created by zhuoxiuwu
 * on 2019-08-26
 * email nimdanoob@gmail.com
 */
public class HelloDex {

    public static void main(String[] args) {
        System.out.println("hello dex!!");
    }
}

javac HelloDex.java

Generate HeeloDex.class

2. Using d8 compiler to generate dex file

d8 HelloDex.class

Generate classes.dex

As mentioned earlier, dex can be interpreted and executed directly by dalivkvm. We can try to execute dex push directly on Android devices.

adb push ./classex.dev /data/local/tmp/hi.dex

adb shell
su
cd /data/local/tmp/
dalvikvm -cp hi.dex HelloDex

Command line output:

hello dex!!

Generate an apk file containing Dex

In the introduction of aapt, we generated an APK file without dex. Now we try to compile the DEX file and merge it into the previous apk.

  1. Compile engineering source code (java)
javac -encoding utf-8 \
-cp ~/Library/Android/sdk/platforms/android-28/android.jar \
app/src/main/java/com/hellobike/androidbuildintroduce/*.java package/com/hellobike/androidbuildintroduce/R.java \
-d classes/

2.class to dex

d8 --lib ~/Library/Android/sdk/platforms/android-28/android.jar \
--release \
--output . \
classes/com/hellobike/androidbuildintroduce/*.class

Generate the classe.dex file in the current directory

3. Use zip command to add dex file to apk file

zip -ur res.apk classes.dex

4.apk byte alignment

First look at the byte alignment in the current compressed package

zipalign -c -v 4 res.apk

output

Verifying alignment of /Users/hb/hellobikeproject/AndroidBuildIntroduce/aaptbuild/link-res.apk (4)...
      49 AndroidManifest.xml (OK - compressed)
     718 res/drawable/ic_launcher_background.xml (OK - compressed)
    1120 res/drawable-v1/ic_launcher_background.xml (OK - compressed)
    1570 res/drawable-v21/ic_launcher_background.xml (OK - compressed)
    2629 res/drawable-v24/$ic_launcher_foreground__0.xml (OK - compressed)
    3039 res/drawable-v24/ic_launcher_foreground.xml (OK - compressed)
    3841 res/layout/activity_main.xml (OK - compressed)
    4091 res/layout-v1/activity_main.xml (OK - compressed)
    4440 res/mipmap-mdpi-v4/ic_launcher.png (OK)
    6570 res/mipmap-mdpi-v4/ic_launcher_round.png (BAD - 2)
    9417 res/mipmap-hdpi-v4/ic_launcher.png (BAD - 1)
   12450 res/mipmap-hdpi-v4/ic_launcher_round.png (BAD - 2)
   17420 res/mipmap-xhdpi-v4/ic_launcher.png (OK)
   21981 res/mipmap-xhdpi-v4/ic_launcher_round.png (BAD - 1)
   28942 res/mipmap-xxhdpi-v4/ic_launcher.png (BAD - 2)
   35401 res/mipmap-xxhdpi-v4/ic_launcher_round.png (BAD - 1)
   45881 res/mipmap-xxxhdpi-v4/ic_launcher.png (BAD - 1)
   54893 res/mipmap-xxxhdpi-v4/ic_launcher_round.png (BAD - 1)
   70092 res/mipmap-anydpi-v26/ic_launcher.xml (OK - compressed)
   70385 res/mipmap-anydpi-v26/ic_launcher_round.xml (OK - compressed)
   70652 resources.arsc (OK)
   74273 classes.dex (OK - compressed)
   75515 META-INF/ANDROIDD.SF (OK - compressed)
   76390 META-INF/ANDROIDD.RSA (OK - compressed)
   77035 META-INF/MANIFEST.MF (OK - compressed)
Verification FAILED

You can see that many resource files are not byte aligned

zipalign -v 4 res.apk zipaligned.apk 

Look at the generated byte aligned apk file again

zipalign -c -v 4 ./zipaligned.apk

Verifying alignment of ./zipaligned.apk (4)...
      49 AndroidManifest.xml (OK - compressed)
     718 res/drawable/ic_launcher_background.xml (OK - compressed)
    1120 res/drawable-v1/ic_launcher_background.xml (OK - compressed)
    1570 res/drawable-v21/ic_launcher_background.xml (OK - compressed)
    2629 res/drawable-v24/$ic_launcher_foreground__0.xml (OK - compressed)
    3039 res/drawable-v24/ic_launcher_foreground.xml (OK - compressed)
    3841 res/layout/activity_main.xml (OK - compressed)
    4091 res/layout-v1/activity_main.xml (OK - compressed)
    4440 res/mipmap-mdpi-v4/ic_launcher.png (OK)
    6572 res/mipmap-mdpi-v4/ic_launcher_round.png (OK)
    9420 res/mipmap-hdpi-v4/ic_launcher.png (OK)
   12456 res/mipmap-hdpi-v4/ic_launcher_round.png (OK)
   17428 res/mipmap-xhdpi-v4/ic_launcher.png (OK)
   21992 res/mipmap-xhdpi-v4/ic_launcher_round.png (OK)
   28956 res/mipmap-xxhdpi-v4/ic_launcher.png (OK)
   35416 res/mipmap-xxhdpi-v4/ic_launcher_round.png (OK)
   45896 res/mipmap-xxxhdpi-v4/ic_launcher.png (OK)
   54908 res/mipmap-xxxhdpi-v4/ic_launcher_round.png (OK)
   70107 res/mipmap-anydpi-v26/ic_launcher.xml (OK - compressed)
   70400 res/mipmap-anydpi-v26/ic_launcher_round.xml (OK - compressed)
   70668 resources.arsc (OK)
   74289 classes.dex (OK - compressed)
   75531 META-INF/ANDROIDD.SF (OK - compressed)
   76406 META-INF/ANDROIDD.RSA (OK - compressed)
   77051 META-INF/MANIFEST.MF (OK - compressed)
Verification succesful

You can see that the output log shows that byte alignment checks were successful

5. Signature

Here we directly use the debug signature key, which is android.

apksigner sign -ks ~/.android/debug.keystore ./zipaligned.apk

6. Install the apk file

adb install -r ./zipaligned.apk

summary

1.dex is the executable file of dalivk virtual machine
2.java code is compiled into classes file through javac, and then compiled into dex file by d8 compiler
3. The resouces.apk + d8 compiled by aapt2 compiled to generate classe.dex file is the final installation package required by android system after merging.
4. After byte-aligned compressed packages are updated or new files are merged, zipalign needs to be restarted.

Posted by mhenke on Tue, 03 Sep 2019 00:05:46 -0700