---
title: "Android应用程序与运行环境"
author: "Perrin Yong"
author_profile: https://www.pystone.net/profile/
published_by: "Perrin Yong"
canonical: https://www.pystone.net/notes/android-app-runtime-environment/
type: note
content_role: unspecified
visibility: public
id_stability: rename-stable
source_path: "10-计算机、信息技术与工程/04-应用开发与云端工程/Android开发/Android应用程序与运行环境.md"
content_hash: 6c9c5bd609ccd3e3ee92e3107f1463517846b756f4b6f0b096f3f522b2150abc
knowledge_version: 224c990773de.5fa8af6e39fa
site_commit: 224c990773de166d23a886306577dd90379529ce
notes_commit: 5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a
---
# Android应用程序与运行环境
JVM（Java Virtual Machine）、Dalvik 和 ART（Android Runtime）从广义上来说，都可以归类为 **"Java 运行时环境"**（Java Runtime Environment）的一部分，核心目标是执行 Java 字节码或类似 Java 的程序。

Dalvik 和 ART可以看作是针对 Android 平台优化的 Java 虚拟机变种，旨在支持 Java 生态和语言特性，负责解释、编译和运行 Java 或 Kotlin 代码（在 Android 中）。

## JVM（Java Virtual Machine）
JVM 是一种运行 Java 字节码（`.class` 文件）的虚拟机，作为 Java 平台的核心组件。它提供了一种跨平台的运行环境，使 Java 程序能够在多种操作系统上运行。

#### **工作原理**
1. **Java 字节码**：Java 源代码（`.java` 文件）通过编译器 `javac` 转换为 `.class` 文件（Java 字节码）。
2. **加载与解释**：JVM 通过类加载器（ClassLoader）加载 `.class` 文件，并将其转换为虚拟机可以执行的指令。
3. **执行方式**：
    - **解释执行**：逐行解释 `.class` 文件中的字节码并执行。
    - **JIT（Just-In-Time）编译**：将热点代码（频繁执行的代码）编译为本地机器码，提高性能。
#### **特点**
- 跨平台性：Java 程序可以在任何安装了 JVM 的系统上运行。
- 面向通用场景：JVM 的设计初衷是服务于多种环境和设备。

## Dalvik

Dalvik 是 Android 早期的虚拟机，用于在移动设备上高效运行 Android 应用程序。它能够运行 Android 专用的 `.dex` 文件（Dalvik Executable）。

#### **工作原理**
1. **字节码格式**：
    - Android 开发中的 `.class` 文件会被转换为 `.dex` 文件，这是一种经过优化的字节码格式。
2. **基于寄存器的架构**：
    - 不同于 JVM 基于栈的指令集，Dalvik 使用寄存器作为操作数存储区。这种方式减少了指令数量，提高了执行效率。
3. **解释执行**：
    - Dalvik 主要通过解释器逐行执行 `.dex` 字节码。

#### **特点**
- **为移动设备优化**：
    - 低内存占用。
    - 更高效的指令集。
- **单独进程模型**：
    - **每个 Android 应用都有自己的 Dalvik 实例，运行在独立的进程中。**
- **GC（垃圾回收）优化**：
    - 针对低内存设备进行了垃圾回收算法优化。

## ART（Android Runtime）

ART 是 Android 的现代运行时，作为 Dalvik 的替代者，从 Android 5.0（Lollipop）开始成为默认运行时。ART 的目标是进一步提高性能，优化资源使用。

#### **工作原理**
1. **AOT（Ahead-Of-Time）编译**：
    - 在应用安装时，ART 会将 `.dex` 文件编译为本地机器码（`ELF` 文件），这样在运行时无需解释或即时编译。
2. **JIT（Just-In-Time）编译**：
    - 从 Android 7.0 开始，ART 增加了 JIT 编译器，用于在运行时优化热点代码。
3. **解释执行**：
    - ART 也支持解释执行未编译的代码。

#### **特点**
- **高性能**：
    - AOT 编译减少了运行时的计算开销，启动速度更快。
- **优化内存使用**：
    - ART 支持共享类和字符串池，减少了重复数据的内存占用。
- **改进的垃圾回收**：
    - ART 提供了更高效的垃圾回收机制（如并行 GC 和增量 GC）。
- **调试和分析支持**：
    - 支持更精细的调试功能，例如更好的堆栈跟踪和内存泄漏检测。

DEX( **Dalvik Executable**) 是 Android 平台的一种字节码格式。
A bytecode format designed specifically for Android that's optimized for a minimal memory footprint.

所有 Android 应用程序的代码最终都会以 DEX 文件的形式运行在 Android Runtime (ART) 或 Dalvik 虚拟机上。


## 特点
- DEX 文件的设计目标是减少运行时的内存使用。
- 指令集被精简并优化，以适应移动设备的有限资源。
* 不同于 Java 的 `.class` 文件（每个类一个文件），一个 DEX 文件可以包含多个类的字节码。这种设计减少了文件数量和存储开销。
- 虽然 DEX 文件是为 Android 优化的，但它仍然保持了平台无关性，类似于 JVM 的字节码。

## 构建

在构建 APK 的过程中，所有 JAR 文件中的 Java 字节码会被 `d8` 或 `dx` 工具转换为 DEX 格式。
- `JAR` 文件中包含的是标准的 Java 字节码（`.class` 文件）。
- 在构建时，这些 `.class` 文件会被统一合并并转换为一个或多个 `.dex` 文件。
- 最终生成的 DEX 文件会被打包到 APK 的 `classes.dex` 文件中。


> Unity 在构建 Android 工程时，会将所有 JAR 插件统一传递给 Android 构建工具链（Gradle 或 `UnityPlayerActivity` 的构建脚本），最终处理方式取决于这些工具链：
> 	- **普通 JAR 文件**：字节码会被转换为 DEX。
> 	- **动态加载 JAR 文件**：如果指定为动态加载，JAR 会保留原始形式。


## 加载和执行
1. **加载 DEX 文件**
DEX 文件通常通过虚拟机加载和解释。加载器主要包括：

- **`ClassLoader`**：加载和解析 DEX 文件中的类。
- **`DexClassLoader`**：支持在运行时动态加载外部的 DEX 文件。

2. **解释与编译**
- **解释执行**：ART 和 Dalvik 虚拟机可以直接解释 DEX 字节码。
- **编译执行**：
    - 在 ART 中，常见方法会被 JIT 编译为本地机器码。
    - 在应用安装时，ART 会将 DEX 文件通过 AOT 编译为本地代码。


## 相关工具
- **d8**：
    - 新版的字节码转换工具，用于将 `.class` 转换为 `.dex`。
    - 比 `dx` 更高效，支持增量编译。
- **dexdump**：
    - 用于分析和查看 DEX 文件内容的工具。
- **proguard**：
    - 用于混淆代码，减小 DEX 文件的大小，并保护代码不被反编译。
