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.
- 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.