---
description: Analyze the Hello application
---

# Exercise 1

## The Java Virtual Machine

The Java bytecode is built for a **Stack Based Machine**.

* Instructions pop values from the stack, and push the result.
* Minimal number of registers (essentially only 2 for arithmetic).
* Stack stores intermediate data.

### Result

* Very few assumptions about the target architecture (number of registers).
* Maximizes compatibility.
* Very compact code.
* Simple tools (compiler), simple state maintenance.

Similar design is used in Cpython, WebAssemble, Postscript, apache Harmony and many others.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FebmZUuEo7g31GaKaHf3F%2FScreenshot%20from%202024-03-03%2018-29-21.png?alt=media&#x26;token=54926f76-a0fc-40ac-bc5a-f1c2533fa705" alt=""><figcaption></figcaption></figure>

## The Android Environment

Android run **Linux** with **binary programs** and **Java applications**.

* Most user space applications are Java (or HTML).
* But can load binary objects through JNI or NDK.

The VM differs from the standard JVM, following a register-based architecture.

* Originally named Dalvik.
* Then evolved to ART after Android 4.4.
* Both environments process the Dalvik bytecode from Dalvik Executable (DEX) files.

Focus on better exploring the capability of the hardware, while having a low footprint.

* Each application is executed in an independent VM instance.
* Crashes and any other side effects are limited to one application.
* Data isolation is ensured by the independent execution environments and forced communication through a single interface.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2F0fqHhIFRnQkNuLDaqzrn%2Fa.png?alt=media&#x26;token=4ef7496d-ac4a-4acf-99bb-e2f3bf96c27f" alt=""><figcaption></figcaption></figure>

## Dalvik VM

Machine models and calling conventions imitate common architectures and C-style calling conventions.

* The machine is register-based, and frames are fixed in size upon creation.
* Each frame consists of several registers (specified by the method) as well as any adjunct data needed to execute the method.
* Registers are considered 32-bit wide. Adjacent register pairs are used for 64-bit values.
* A function may access up to 65535 registers, usually only 16, but 256 may be common.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2F8ZvgTVpt1dIfQrekLiqM%2FScreenshot%20from%202024-03-03%2018-44-58.png?alt=media&#x26;token=ae6f557d-187c-4bf6-b959-611d638b6d05" alt=""><figcaption></figcaption></figure>

Before execution, **files are optimized** for faster execution.

* Some optimizations include resolving methods and updating the **`vtable`**.
  * Methods have a signature that must be resolved to an actual **`vtable`** entry. Optimization changes bytecode by resolving the method location (index) in the vtable.
* The result is stored as a **`odex`** file in the `/system/cache`.
  * Applications are stored "twice" as standard (APK with DEX) and optimized versions (ODEX).

Bytecode is processed using **Just-in-time** (JIT) approach.

* The VM will compile and translate code in Real-time, during execution.
* Garbage collection tasks also execute in the foreground (impact on performance).

## DEX files

Dalvik EXecutable files are the standard execution format for previous Android versions.

* Created with the **`dx`** command:
  * In reality: `java -Xmx1024M -jar ${SDK_ROOT}.../lib/dx.jar`
* However, the format is still relevant in current systems.

Contains Java bytecode that was converted to Dalvik bytecode.

* Java uses stack +4 registers, while DEX uses 0-v65535 registers.
  * DEX registers can be mapped to ARM registers (ARM has 10 general-purpose registers).
* Optimized to constraint devices, but not so compact as instructions may be larger.
  * 1-5 bytes fo java, instead of 2-10 bytes.

DEX is highly like Java and bytecode can be **converted both ways**.

* `dx` compiles `.jar` to `.dex`, `dex2jar` decompiles `.dex` to `.jar`.
* Allows reengineering applications (download apk, reversing, change, build, sign, publish to store).

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FQudFRfzXUIjlihZ2UE2v%2FScreenshot%20from%202024-03-03%2019-16-24.png?alt=media&#x26;token=2d4f818e-c77f-4140-b030-dc8ed2660d6c" alt=""><figcaption></figcaption></figure>

## DEX and Java Bytecode

| DEX Opcode                                                                                                 | Java Bytecode                                                                                            | Purpose                                |
| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| <p>60-66:sget-*<br>52-58:iget-*</p>                                                                        | <p>b2:getstatic<br>b4:getfield</p>                                                                       | Read a static or instance variable     |
| <p>67-6d:sput<br>59-5f:iput</p>                                                                            | <p>b3:putstatic<br>b5:putfield</p>                                                                       | Write a static or instance variable    |
| <p>6e:invoke-virtual<br>6f:invoke-super<br>70:invoke-direct<br>71:invoke-static<br>72:invoke-interface</p> | <p>b6:invokevirtual<br>ba:invokedynamic<br>b7:invokespecial<br>b8:invokestatic<br>b9:invokeinterface</p> | Call a method                          |
| 20:instance-of                                                                                             | c1:instanceof                                                                                            | Return true if obj is of class         |
| 1f:check-cast                                                                                              | c0:checkcast                                                                                             | Check if a type cast can be performed  |
| bb:new                                                                                                     | 22:new-instance                                                                                          | New (unconstructed) instance of object |
| 12-1c:const\*                                                                                              | <p>12:iidc<br>13:idc_w<br>14:idc2_w</p>                                                                  | Define constant                        |
| 21: array-lenght                                                                                           | be:arraylength                                                                                           | Get length of an array                 |
| 23:new-array                                                                                               | bd:anewarray                                                                                             | Instantiate an array                   |
| 24-25:filled-new-array\[/range]                                                                            |  N/A                                                                                                     | Populate an array                      |
| <p>32..37:if-*<br>38..3d:if-*z</p>                                                                         | <p>a0-a6:if_icmp*<br>99-9e:if*</p>                                                                       | Branch on logical                      |
| 2b:packed-switch                                                                                           | ab:lookupswitch                                                                                          | Switch statement                       |
| 2c:sparse-switch                                                                                           | aa:tableswitch                                                                                           | Switch statement                       |
| <p>28:goto<br>29:goto/16<br>30:goto/32</p>                                                                 | <p>a7:goto<br>c8:goto_w</p>                                                                              | Jump to offset in code                 |
| 27: throw                                                                                                  | bf:athrow                                                                                                | Throw exception                        |

## Android RunTime (ART)

Alternative runtime which presents an **optimized execution path**.

* Introduced in Android 4.4, implemented in C++, and supports 64bits.
* Run OAT files, which contain native code (not bytecode).
* References to Java objects point towards C++ objects managed by the VM.
  * While application logic is expressed in Java, framework methods actually execute in native code.

ART introduces **ahead-of-time** (AOT) compilation.

* **At install time, ART compiles apps using the on-device dex2oat tool**.
* This utility accepts DEX files as input and generates a compiled app executed for the target device.
* Improves performance over ODEX files as file repetitive load operations are avoided.

Improves Garbage Collection by optimizing memory usage.

* Avoiding GC driven app pauses.
* Overall, it provides much better performance.
* JIT is not that efficient and doing it in real time hurts performance and battery.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FKYboiNrGkbtMAPwXEYl9%2FScreenshot%20from%202024-03-03%2020-12-45.png?alt=media&#x26;token=92b4940b-eecb-4c16-9f66-d6ddc5390021" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FF0W4a2xYyEw9f4Au9JDv%2FScreenshot%20from%202024-03-03%2020-13-10.png?alt=media&#x26;token=a3ad893e-b415-40d7-b6c3-04df042bd169" alt=""><figcaption></figcaption></figure>

## ART specific files

* `.oat` – only at `/system/framework/[arch]/boot.oat`
  * Main ART format, OAT: Of Ahead Time (from Ahead of Time).
    * “_We went with that because then we say that process of converting .dex files to .oat files would be called quakerizing and that would be really funny._”, reference to the Quaker Oats Company
* `.odex` – an `.OAT` file containing the precompiled applications
  * Although it uses the same extension, .odex files with ART are .OAT files, in reality, ELF files.
  * Stored in `/data/dalvik-cache`
    * But Dalvik is not used with ART…
* `.art` – only at `/system/framework/[arch]/boot.art`
  * An .OAT file containing vital framework classes (base Java classes to be used by ART).
* `.vdex` - contains the uncompressed DEX code of the APK, with some additional metadata to speed up verification.
  * Assumed to be already verified DEX files.

## OAT files (or DEX files in ART, which are also OAT)

* Are ELF files containing DEX code.
  * OAT Header, followed by DEX files in an ELF container.
    * DEX files can be extracted with oat2dex.
* Java methods in DEX file are mirrored in C++
  * `java.lang.String:` -> `art::mirror::String`
  * When the Java code creates an object, the object is created in the C++ (native) code by the VM.
    * JVM handles references to the C++ object.
* On boot, common objects are instantiated (ones in Android Framework) by loading boot.art.
  * To speed up execution as such classes are required by most applications.
