Download as pdf or txt
Download as pdf or txt
You are on page 1of 116

Journey of APK from

Compile to Start

@droid_singh @_romichandra_
“Success is a journey not a destination”
- Internet
Components of APK
Components of APK
Basic
Components of APK
Complex
Where do these come from?
Lets magnify this 🤔🔎
😨
AAPT

•Android Asset Packaging tool.


•Creates R.java file.
•Tool for creating, updating and viewing
components the zip archive.
AAPT

•Android Asset Packaging tool.


•Creates R.java file.
•Tool for creating, updating and viewing
components the zip archive.
How R is prepared?
•IDs are generated by AAPT to refer resources.
•Resource bit:
P P T T N N N N

0x7f
How R is prepared?
•IDs are generated by AAPT to refer resources.
Category
•Resource bit:
P P T T N N N N

0x7f Next hex available


public static final class id {
public static final int ALT=0x7f070000;
public static final int CTRL=0x7f070001;
public static final int FUNCTION=0x7f070002;
public static final int META=0x7f070003;
public static final int SHIFT=0x7f070004;
public static final int SYM=0x7f070005;
public static final int action_bar=0x7f070006;
public static final int action_bar_activity_content=0x7f070007;
public static final int action_bar_container=0x7f070008;
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height=“match_parent">

</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/action_bar_constraintLayout"
android:layout_width="match_parent"
android:layout_height=“match_parent">

</android.support.constraint.ConstraintLayout>
public static final class id {
public static final int ALT=0x7f070000;
public static final int CTRL=0x7f070001;
public static final int FUNCTION=0x7f070002;
public static final int META=0x7f070003;
public static final int SHIFT=0x7f070004;
public static final int SYM=0x7f070005; NNNN
public static final int action_bar=0x7f070006;
public static final int action_bar_activity_content=0x7f070007;
public static final int action_bar_constraintLayout=0x7f070008;
public static final int action_bar_container=0x7f070009;
}
TT
PP
R

Java/Kt files Resources

R.id.action_constraintLayout
javac

Java class

javac
Java class
dx
Proguard dex
or
javac d8
Java class

javac
Java class

.
.
.
.
javac

Java class

javac
Java class
dx
Proguard dex
or
javac d8
Java class

javac
Java class

.
.
.
.
javac

Java class

javac
Java class
dx
Proguard dex
or
javac d8
Java class

javac
Java class

.
.
.
.
javac

Java class

javac
Java class
dx
Proguard dex
or
javac d8
Java class

javac
Java class

.
.
.
.
javac

Java class

javac
Java class
dx
Proguard dex
or
javac d8
Java class

javac Optimization
Java class
layers
.
.
.
.
public static long sumArray(int[] arr){
long sum = 0;
for(int i: arr){
sum += i;
}
return sum;
}
public static long sumArray(int[] arr){ public static long sumArray(int[]);
Code:
long sum = 0; 0: lconst_0
1: lstore_1
for(int i: arr){ 2: aload_0
sum += i; 3: astore_3
4: aload_3
} 5: arraylength
6: istore 4
return sum; 8: iconst_0
} 9: istore 5
11: iload 5
13: iload 4
15: if_icmpge 36
18: aload_3 .class
19: iload 5
21: iaload
22: istore 6
24: lload_1
25: iload 6
27: i2l
28: ladd
29: lstore_1
30: iinc 5, 1
33: goto 11
36: lload_1
37: lreturn
public static long sumArray(int[] arr){ public static long sumArray(int[]);
Code:
long sum = 0; 0: lconst_0
1: lstore_1
for(int i: arr){ 11: iload 5 2: aload_0
sum += i; 13: iload 4 3: astore_3
4: aload_3
} 15: if_icmpge 36 5: arraylength
6: istore 4
return sum; 18: aload_3 8: iconst_0
} 19: iload 5 9: istore 5
11: iload 5
21: iaload
🔍 13: iload 4

Dispatches 14
22: istore 6 15: if_icmpge 36
18: aload_3 .class
24: lload_1 19: iload 5
Read 20 25: iload 6 21: iaload
22: istore 6

Write 16 27: i2l 24: lload_1


25: iload 6
28: ladd 27: i2l
28: ladd
29: lstore_1 29: lstore_1
30: iinc 5, 1 30: iinc 5, 1
33: goto 11
33: goto 11 36: lload_1
37: lreturn
public static long sumArray(int[] arr){
long sum = 0;
for(int i: arr){
sum += i;
}
return sum;
}
public static long sumArray(int[] arr){
long sum = 0;
for(int i: arr){
sum += i; .dex:
}
0000: const-wide/16 v2, #int 0 // #0
return sum;
0002: array-length v1, v6
}
0003: const/4 v0, #int 0 // #0
0004: if-ge v0, v1, 000d // +0009
0006: aget v4, v6, v0
0008: int-to-long v4, v4
0009: add-long/2addr v2, v4
000a: add-int/lit8 v0, v0, #int 1 // #01
000c: goto 0004 // -0008
000d: return-wide v2
public static long sumArray(int[] arr){ Dispatches 6
long sum = 0; Reads 10
for(int i: arr){
Writes 6
sum += i; .dex:
}
0000: const-wide/16 v2, #int 0 // #0
return sum;
0002: array-length v1, v6
}
0003: const/4 v0, #int 0 // #0
0004: if-ge v0, v1, 000d // +0009 0004: if-ge v0, v1, 000d // +0009
0006: aget v4, v6, v0 0006: aget v4, v6, v0
0008: int-to-long v4, v4
0008: int-to-long v4, v4
0009: add-long/2addr v2, v4 🔍 000a: add-int/lit8 v0, v0, #int 1 // #01
0009: add-long/2addr v2, v4

000a: add-int/lit8 v0, v0, #int 1 // #01 000c: goto 0004 // -0008
000c: goto 0004 // -0008 000d: return-wide v2
ZipAlign
ZipAlign
•Android has a 4 byte boundary memory mapping
ZipAlign
•Misaligned data slows data access performance.
ZipAlign
•Misaligned data slows data access performance.

•ZipAlign step results in aligning all the data in 4 byte


boundary.
Installation

Compilation
Dalvik

Upto KitKat
Dalvik
•Byte Code Verification

Upto KitKat
Dalvik
•Byte Code Verification
To check the integrity of Dex

Upto KitKat
Dalvik
•Byte Code Verification
To check the integrity of Dex
Done at install time rather than run
time.

Upto KitKat
Dalvik
•Byte Code Verification
To check the integrity of Dex
Done at install time rather than run
time.
Validity of indices and structure of
file.
Upto KitKat
Dalvik
•Byte Code Verification
To check the integrity of Dex
Done at install time rather than run
time.
Validity of indices and structure of
file.
Upto KitKat
Ordering of the instructions.
Dalvik
•Optimizations

Upto KitKat
Dalvik
•Optimizations
VTable Method Index for method
invocation.

Upto KitKat
Dalvik
•Optimizations
VTable Method Index for method
invocation.
Replacing high volume of methods
with their inline versions.

Upto KitKat
Dalvik
•Optimizations
VTable Method Index for method
invocation.
Replacing high volume of methods
with their inline versions.

Prune empty methods.


Upto KitKat
Dalvik
•Optimizations
VTable Method Index for method
invocation.
Replacing high volume of methods
with their inline versions.

Prune empty methods.


Upto KitKat
Pre computations.
Dalvik
•Optimizations
VTable Method Index for method
invocation.
Replacing high volume of methods
with their inline versions.

Prune empty methods.


Upto KitKat
Pre computations. X 😎
DE
O
o p t
dex
ART

In Lollipop
ART
•Preloading
boot.art

boot.oat

In Lollipop
ART
•Preloading
boot.art

boot.oat

•Load Compiler
Compiler
In Lollipop Driver

ELF file
ART
•Preloading
boot.art

boot.oat

•Load Compiler (AOT😎)


Compiler
2 O at
In Lollipop Driver d ex

ELF file
ART
•Preloading Dex

boot.art Resolve
classes
boot.oat
Verify
classes
•Load Compiler
Compiler Init
🔎
Driver classes

Compile ELF
ELF file File
classes
Problem:
Problem:
Hybrid: JIT+AOT
Hybrid: JIT+AOT

From Android Nougat


Profile guided Compilation
App

App Execution
(Interpret/JIT)

Profile Files

Profile guided
compile

Compiled App
dex file,
oat file
dex file, ART
oat file
dex file, ART
oat file

Execute
method
dex file, ART
oat file

Execute
method

Is
it compiled
?
dex file, ART
oat file

Execute
method

Y Is
it compiled
?
dex file, ART
oat file

Execute
method

Is it Is
Y
JIT
it compiled
compiled
?
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
Y

Run code
from jit cache
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
Y N

Run code
Interpreter
from jit cache
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
Y N

Record
Run code Profiles
Interpreter
from jit cache info
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
Y N

Record Is
Run code Profiles it hot?
Interpreter
from jit cache info
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
Y N

Record Is
Y JIT
Run code Profiles it hot?
Interpreter Cache
from jit cache info
dex file, ART
oat file

Run code
from .oat Execute
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
N
Y N

Record Is
Y JIT
Run code Profiles it hot?
Interpreter Cache
from jit cache info
dex file, ART
oat file When Profile guided
Run code compilation
from .oat Execute occurs? 🤔
file method
N
Is it Is
Y
JIT
it compiled
compiled
?
N
Y N

Record Is
Y JIT
Run code Profiles it hot?
Interpreter Cache
from jit cache info
When Profile guided
compilation
occurs? 🤔
Installation

Compilation Optimizations
“Abstractions increase the productivity of developer but they
can be overhead for runtime”
Optimizations
1. Constant Folding

numberOfDays = 2 + 2 + previous;

add-int/lit8 v0, v2, #int 4


2. Inlining
fun len (string: String): Int{
return string.length
}
2. Inlining
fun len (string: String): Int{
return string.length
}

const-string v0, "string"


invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull
invoke-virtual {v1}, Ljava/lang/String;.length
move-result v0
return v0
2. Inlining
fun len (string: String): Int{
return string.length
}

const-string v0, "string"


invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull
invoke-virtual {v1}, Ljava/lang/String;.length
move-result v0
return v0
const-string v0, "string"
if-nez v1, :continue
invoke-static {v1}, throwParameterIsNullException
:continue
invoke-virtual {v1}, Ljava/lang/String;.length
move-result v0
return v0
3. Bounds Check Elimination

int sum = 0;
for (int i = 0; i < size; i++) {
sum += array[i];
}
3. Bounds Check Elimination

int sum = 0;
for (int i = 0; i < size; i++) {
sum += array[i];
}
4. Strength Reduction
5. Dead Code Elimination
6. DexLayout
7. Class Hierarchy Analysis
And much more…..
??

Compilation
MULTIDEX: The 64k LIMIT
MULTIDEX: THE AFTERMATH
• Adverse effect on App Startup
• Build time increases.
• Strange errors during runtime
• Strangers in Crashyltics..
MULTIDEX: THE AFTERMATH
• Adverse effect on App Startup
• Build time increases.
• Strange errors during runtime
• Strangers in Crashyltics..
MULTIDEX: THE AFTERMATH
• Adverse effect on App Startup
• Build time increases.
• Strange errors during runtime
• Strangers in Crashyltics..
MULTIDEX: HOW?
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Release the lock
Copyright: AOSP
Write
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Release the lock
Copyright: AOSP
Write
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Release the lock
Copyright: AOSP
Write
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Write Release the lock
Copyright: AOSP
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Write Release the lock
Copyright: AOSP
.class

DirectClass
FileConsumer

Validate & Lock

ClassTranslatorTask

ClassDefItemConsumer

Update global indices


Write Release the lock
Copyright: AOSP
App
Installation Startup

Compilation Optimizations
App Startup:
Evolving Better with ART
😣
What’s wrong?🤔
10s
Time for tips
• Use lazy initializations.
• Don’t use reflections at time of APP startup
• Initialize all the SDKs in background
• Load images asynchronously.
• Avoid nesting layout
Let us all be an ARTist
Thank you'

@droid_singh @_romichandra_
amanjeetsingh150 romichandra

You might also like