一、Android Runtime (ART) 概述
Android Runtime (ART) 是 Android 操作系统的核心组件,负责执行应用程序的字节码。自 Android 5.0 (API 级别 21) 起,ART 取代了 Dalvik 虚拟机,成为 Android 的默认运行时环境。与 Dalvik 相比,ART 提供了更好的性能、更低的内存占用和更高效的电池使用,这些改进主要得益于其提前编译 (Ahead-Of-Time, AOT) 技术。
ART 的主要职责包括:
- 应用程序的加载和执行
- 内存管理与垃圾回收
- 安全机制的实现
- 与 Android 系统其他组件的交互
ART 采用模块化设计,包含多个核心子系统,如类加载器、字节码验证器、即时编译器 (JIT)、提前编译器 (AOT)、垃圾回收器、调试支持等。这些组件协同工作,确保应用程序在 Android 设备上高效、稳定地运行。
二、AOSP 代码树结构基础
Android Open Source Project (AOSP) 的代码树是一个庞大而复杂的系统,包含了 Android 操作系统的所有源代码。理解 AOSP 代码树的组织结构对于定位和分析 ART 源码至关重要。
AOSP 代码树的顶级目录结构如下:
.
├── bionic/ # C/C++ 标准库实现
├── bootable/ # 启动相关代码
├── build/ # 编译系统和工具
├── cts/ # 兼容性测试套件
├── dalvik/ # Dalvik 虚拟机 (已弃用)
├── development/ # 开发工具和示例
├── device/ # 设备特定的配置和驱动
├── frameworks/ # 核心框架代码
├── hardware/ # 硬件抽象层
├── libcore/ # Java 核心库
├── ndk/ # Native Development Kit
├── out/ # 编译输出目录
├── packages/ # 系统应用和框架
├── prebuilts/ # 预编译的二进制文件
├── sdk/ # SDK 相关工具
├── system/ # 系统级组件
├── test/ # 测试框架和用例
└── vendor/ # 厂商特定代码
ART 源码主要位于 art/
目录下,但也涉及其他多个目录,如 libcore/
、dex/
、tools/
等。这些目录共同构成了 ART 的完整实现。
三、ART 源码在 AOSP 中的核心位置
ART 源码主要集中在 art/
目录下,该目录包含了 ART 运行时的核心实现。以下是 art/
目录的主要子目录结构:
art/
├── base/ # 基础库和工具类
├── compiler/ # 编译器实现 (AOT 和 JIT)
├── dex2oat/ # DEX 到 OAT 转换工具
├── debugger/ # 调试器实现
├── gc/ # 垃圾回收器实现
├── interpreter/ # 字节码解释器
├── jit/ # 即时编译器
├── libart/ # ART 核心库
├── linker/ # 运行时链接器
├── mirror/ # Java 类镜像实现
├── oat/ # OAT 文件格式和处理
├── profiler/ # 性能分析工具
├── runtime/ # 运行时核心实现
├── test/ # 测试框架和用例
├── tools/ # 开发工具
└── verifier/ # DEX 字节码验证器
3.1 base/ 目录
base/
目录包含了 ART 运行时使用的基础库和工具类,这些组件为整个 ART 系统提供了底层支持。主要组件包括:
android-base/
:Android 基础库的封装bit_utils.h
:位操作工具logging.h
:日志系统mutex.h
:同步原语os.h
:操作系统抽象层string_view.h
:字符串视图实现thread_state.h
:线程状态管理
这些基础组件被 ART 的各个模块广泛使用,确保了代码的可维护性和跨平台兼容性。
3.2 compiler/ 目录
compiler/
目录实现了 ART 的编译系统,包括 AOT 编译器和 JIT 编译器。主要组件包括:
driver/
:编译器驱动程序optimizing/
:优化编译器实现utils/
:编译工具和辅助类dex_compilation_unit.h
:DEX 编译单元compiler_options.h
:编译选项配置
ART 的编译器能够将 Dalvik 字节码 (DEX) 转换为本地机器码,从而提高应用程序的执行效率。优化编译器实现了多种优化技术,如内联、常量传播、循环优化等。
3.3 gc/ 目录
gc/
目录实现了 ART 的垃圾回收系统。ART 采用了多种垃圾回收算法,以平衡内存使用和应用程序性能。主要组件包括:
collector/
:垃圾回收器实现 (标记-清除、标记-整理等)heap.h
:堆内存管理space/
:内存空间管理object_allocator.h
:对象分配器gc_scheduler.h
:垃圾回收调度器
ART 的垃圾回收系统在不同版本中不断演进,从 Android 5.0 的 CMS (Concurrent Mark Sweep) 到 Android 6.0 的并发标记-整理,再到 Android 8.0 的 G1 垃圾回收器,性能不断提升。
3.4 runtime/ 目录
runtime/
目录是 ART 运行时的核心,实现了线程管理、类加载、方法调用等关键功能。主要组件包括:
thread.h
:线程实现class_linker.h
:类链接器method_inliner.h
:方法内联器interpreter.h
:字节码解释器jni_env.h
:JNI 环境实现monitor.h
:监视器和同步机制
运行时组件负责管理应用程序的执行环境,确保 Java 代码能够在 Android 设备上正确运行。
四、ART 与其他 AOSP 组件的关系
ART 不是一个孤立的组件,而是与 AOSP 中的其他多个组件密切协作。理解这些关系对于全面掌握 ART 的工作原理至关重要。
4.1 与 Dalvik 的关系
虽然 ART 自 Android 5.0 起取代了 Dalvik 虚拟机,但在 AOSP 代码树中仍然保留了 Dalvik 的源码 (dalvik/
目录)。这主要是为了兼容性考虑,以及作为历史参考。ART 在设计上借鉴了 Dalvik 的许多概念,但采用了不同的执行模式:
- Dalvik 使用即时编译 (JIT) 技术,在应用运行时将字节码转换为机器码
- ART 使用提前编译 (AOT) 技术,在应用安装时或系统编译时将字节码转换为机器码
这种差异使得 ART 能够提供更好的性能和响应速度。
4.2 与 libcore 的关系
libcore/
目录包含了 Java 核心库的实现,这些库为应用程序提供了基本的 API。ART 与 libcore 紧密协作,确保 Java 代码能够正确执行。例如:
libcore/ojluni/
:OpenJDK 核心库的 Android 实现libcore/dalvik/
:Dalvik 特定的核心库实现libcore/luni/
:早期 Android 核心库实现
ART 通过类加载器机制加载这些核心库,并与它们进行交互。例如,当应用程序调用 java.lang.Object
类的方法时,ART 会找到对应的本地实现并执行。
4.3 与 Android 框架的关系
Android 框架 (frameworks/
) 提供了应用程序开发的高级 API,ART 负责执行这些框架代码。两者之间的交互主要通过以下方式实现:
- Binder 机制:用于进程间通信 (IPC)
- Android 运行时 API:如 Context、Activity 等
- 系统服务:如 WindowManager、PackageManager 等
ART 为这些框架组件提供了执行环境,确保它们能够高效运行。同时,Android 框架也为 ART 提供了必要的系统服务和资源管理。
4.4 与 Bionic C 库的关系
Bionic (bionic/
) 是 Android 的 C 标准库实现,ART 依赖 Bionic 提供的底层系统调用和库函数。例如:
- 文件操作
- 网络通信
- 内存管理
- 线程和同步
ART 通过 Bionic 与 Linux 内核进行交互,获取系统资源和服务。这种依赖关系确保了 ART 能够在 Android 设备上高效运行。
五、ART 源码中的关键数据结构
ART 源码中定义了许多关键的数据结构,这些结构是理解 ART 工作原理的基础。以下是一些最重要的数据结构及其源码分析。
5.1 ArtMethod 结构
ArtMethod
结构表示 Java 方法的运行时表示。它包含了方法的元数据和执行所需的信息。
// art/runtime/method.h
class ArtMethod FINAL {
public:
// 方法的访问标志
uint32_t access_flags_;
// 方法在 DEX 文件中的索引
uint32_t dex_code_item_offset_;
uint32_t dex_method_index_;
// 指向声明该方法的类
GcRoot<mirror::Class> declaring_class_;
// 方法的入口点,根据编译状态可能指向不同的实现
void* entry_point_from_quick_compiled_code_;
void* entry_point_from_interpreter_;
// 方法的字节码或编译后的机器码
union {
const uint8_t* dex_code_; // 解释执行时使用
const void* native_code_; // 编译执行时使用
};
// 其他方法属性和辅助函数...
// 判断方法是否已编译
bool IsCompiled() const {
return entry_point_from_quick_compiled_code_ != nullptr;
}
// 获取方法的入口点
void* GetEntryPoint() const {
if (IsCompiled()) {
return entry_point_from_quick_compiled_code_;
} else {
return entry_point_from_interpreter_;
}
}
};
ArtMethod
结构是方法调用的核心,它根据方法的编译状态决定是通过解释器执行还是直接执行编译后的机器码。
5.2 mirror::Object 类
mirror::Object
是所有 Java 对象的基类,它定义了对象的基本结构和操作。
// art/runtime/mirror/object.h
namespace art {
namespace mirror {
class PACKED(4) Object {
protected:
// 对象头,包含哈希码、分代年龄和锁状态等信息
HeapReference<Class> class_;
uint32_t monitor_;
public:
// 获取对象的类
Class* GetClass() const {
return class_.Read();
}
// 检查对象是否为数组
bool IsArrayInstance() const {
return GetClass()->IsArrayClass();
}
// 其他对象操作...
// 对象分配方法
static Object* Alloc(Thread* self, Class* klass, size_t byte_count,
size_t* bytes_allocated, size_t* usable_size,
bool alloc_with_finalizer);
};
} // namespace mirror
} // namespace art
mirror::Object
类定义了对象的基本布局和操作接口,所有 Java 对象在运行时都以这个结构为基础。对象头 (class_
和 monitor_
) 包含了对象的类型信息和同步状态。
5.3 DexFile 结构
DexFile
结构表示 Dalvik 可执行文件 (DEX),它包含了应用程序的字节码和元数据。
// art/runtime/dex_file.h
class DexFile final {
public:
// DEX 文件头
struct Header {
uint8_t magic_[8]; // 魔数,标识文件类型
uint32_t checksum_; // Adler32 校验和
uint8_t signature_[20]; // SHA-1 签名
uint32_t file_size_; // 文件总大小
uint32_t header_size_; // 头部大小
uint32_t endian_tag_; // 字节序标记
// 其他头部字段...
};
// DEX 文件的各种数据区域
const Header* const header_;
const uint8_t* const data_begin_;
const uint8_t* const data_end_;
// 字符串、类型、方法和字段的索引表
const StringId* const string_ids_;
const TypeId* const type_ids_;
const ProtoId* const proto_ids_;
const FieldId* const field_ids_;
const MethodId* const method_ids_;
const ClassDef* const class_defs_;
// 构造函数和解析方法
explicit DexFile(const uint8_t* base, size_t size, const std::string& location,
uint32_t location_checksum, const OatDexFile* oat_dex_file = nullptr);
bool Initialize(std::string* error_msg);
// 获取各种索引表的方法
size_t NumStringIds() const { return header_->string_ids_size_; }
size_t NumTypeIds() const { return header_->type_ids_size_; }
size_t NumMethodIds() const { return header_->method_ids_size_; }
// 其他方法...
};
DexFile
结构负责解析和管理 DEX 文件的内容,为类加载器和字节码验证器提供数据支持。
5.4 ClassLinker 类
ClassLinker
类负责类的加载、链接和初始化,是 ART 运行时的核心组件之一。
// art/runtime/class_linker.h
class ClassLinker {
public:
// 加载类的方法
mirror::Class* FindClass(Thread* self, const char* descriptor, Handle<mirror::ClassLoader> class_loader);
mirror::Class* DefineClass(Thread* self, const char* descriptor, Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file, const DexFile::ClassDef& class_def);
// 链接和初始化类的方法
bool LinkClass(Thread* self, Handle<mirror::Class> klass);
bool EnsureInitialized(Thread* self, Handle<mirror::Class> klass, bool can_init, bool defer_init);
// 解析字段和方法的方法
mirror::ArtField* ResolveField(Thread* self, uint32_t field_idx, Handle<mirror::Class> ref_class,
bool is_static, bool for_initialization);
mirror::ArtMethod* ResolveMethod(Thread* self, uint32_t method_idx, Handle<mirror::Class> ref_class,
bool is_static, bool for_initialization);
// 其他类加载和链接相关方法...
private:
// 类加载锁和缓存
ReaderWriterMutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
ClassTable classes_ GUARDED_BY(lock_);
std::unordered_map<std::string, ClassLoaderData> class_loader_data_ GUARDED_BY(lock_);
};
ClassLinker
实现了 Java 类加载机制的核心逻辑,包括类的查找、定义、链接和初始化等过程。
六、ART 源码中的编译系统
ART 的编译系统负责将 Dalvik 字节码转换为本地机器码,提高应用程序的执行效率。ART 采用了混合编译策略,结合了 AOT (Ahead-Of-Time) 编译、JIT (Just-In-Time) 编译和解释执行。
6.1 AOT 编译流程
AOT 编译在应用安装时或系统编译时进行,将字节码预先编译为本地机器码。主要流程如下:
- dex2oat 工具:负责将 DEX 文件转换为 OAT (Optimized Android Archive) 文件。
// art/dex2oat/dex2oat.cc
int main(int argc, char** argv) {
// 解析命令行参数
RuntimeArgumentMap runtime_options;
CompilerOptions compiler_options;
std::vector<std::string> input_files;
std::string output_filename;
// 解析参数...
// 初始化运行时
Runtime* runtime = Runtime::Create(runtime_options);
if (runtime == nullptr) {
LOG(ERROR) << "Failed to create runtime";
return 1;
}
// 创建编译驱动
std::unique_ptr<CompilationDriver> driver(
new CompilationDriver(runtime, &compiler_options));
// 编译 DEX 文件
std::vector<const DexFile*> dex_files;
for (const std::string& input_file : input_files) {
std::unique_ptr<const DexFile> dex_file = OpenDexFile(input_file);
if (dex_file == nullptr) {
LOG(ERROR) << "Failed to open DEX file: " << input_file;
return 1;
}
dex_files.push_back(dex_file.release());
}
// 执行编译
std::unique_ptr<const OatFile> oat_file = driver->CompileAll(dex_files);
if (oat_file == nullptr) {
LOG(ERROR) << "Compilation failed";
return 1;
}
// 写入 OAT 文件
if (!WriteOatFile(output_filename, *oat_file)) {
LOG(ERROR) << "Failed to write OAT file";
return 1;
}
return 0;
}
- 编译驱动:协调编译过程,包括前端解析、中间代码生成、优化和后端代码生成。
// art/compiler/driver/compilation_driver.h
class CompilationDriver {
public:
// 编译所有 DEX 文件
std::unique_ptr<const OatFile> CompileAll(const std::vector<const DexFile*>& dex_files);
// 编译单个方法
bool CompileMethod(ArtMethod* method, Thread* thread, const DexFile& dex_file,
uint32_t method_idx, CompilationUnit* cu);
// 优化和生成代码
bool Optimize(CompilationUnit* cu, HGraph* graph);
bool GenerateCode(CompilationUnit* cu, HGraph* graph, const CodeGenerator& codegen);
// 其他编译相关方法...
};
- 优化编译器:实现各种优化技术,提高生成代码的性能。
// art/compiler/optimizing/optimizing_compiler.h
class OptimizingCompiler {
public:
// 构建中间表示 (IR) 图
std::unique_ptr<HGraph> BuildGraph(const DexFile::CodeItem* code_item,
CompilationUnit* cu);
// 应用各种优化
void RunOptimizations(HGraph* graph, CompilationUnit* cu);
// 执行特定优化
void RunRegisterAllocation(HGraph* graph, CompilationUnit* cu);
void RunInstructionScheduling(HGraph* graph, CompilationUnit* cu);
void RunInlining(HGraph* graph, CompilationUnit* cu);
// 其他优化方法...
};
6.2 JIT 编译流程
JIT 编译在应用运行时进行,针对热点方法进行编译,提高这些方法的执行效率。主要流程如下:
- JIT 编译器初始化:在运行时启动 JIT 编译器。
// art/jit/jit.cc
bool Jit::Start(Thread* self, bool profiling_enabled) {
// 创建 JIT 编译器实例
jit_compiler_.reset(new JitCompiler());
// 初始化 JIT 编译线程
jit_thread_.reset(new JitThread());
if (!jit_thread_->Start()) {
LOG(ERROR) << "Failed to start JIT thread";
return false;
}
// 启用方法采样
if (profiling_enabled) {
StartProfiling();
}
return true;
}
- 方法采样和热点检测:监控方法执行,识别热点方法。
// art/jit/profiler.cc
void Profiler::SampleMethod(ArtMethod* method) {
// 更新方法执行计数器
std::lock_guard<std::mutex> lock(mutex_);
MethodData* data = GetMethodData(method);
if (data != nullptr) {
data->increment_sample_count();
// 检查是否达到编译阈值
if (data->sample_count() >= jit_threshold_) {
RequestCompilation(method);
}
}
}
void Profiler::RequestCompilation(ArtMethod* method) {
// 将方法添加到编译队列
jit_->EnqueueCompilation(method, kCompilationKindHot);
}
- JIT 编译执行:在后台线程中编译热点方法。
// art/jit/jit_compiler.cc
bool JitCompiler::CompileMethod(ArtMethod* method, Thread* thread,
CompilationKind kind) {
// 创建编译参数
CompilerOptions options;
// 设置编译选项...
// 创建编译驱动
std::unique_ptr<CompilationDriver> driver(
new CompilationDriver(runtime_, &options));
// 获取方法的 DEX 信息
const DexFile* dex_file = method->GetDexFile();
uint32_t dex_method_idx = method->GetDexMethodIndex();
// 编译方法
return driver->CompileMethod(method, thread, *dex_file, dex_method_idx, nullptr);
}
6.3 解释执行
对于未编译的方法,ART 使用解释器执行字节码。解释器实现了字节码的逐条执行。
// art/interpreter/interpreter.cc
JValue Execute(Thread* self, const DexFile::CodeItem* code_item,
ShadowFrame* shadow_frame, JValue result_register,
bool trace, bool log_interpreter_usage) {
// 获取字节码数组和方法信息
const uint16_t* insns = code_item->insns_;
uint32_t dex_pc = 0;
// 解释执行循环
while (true) {
// 获取当前指令
uint16_t opcode = insns[dex_pc] & 0xff;
// 根据操作码执行相应操作
switch (opcode) {
case Instruction::NOP:
dex_pc += 1;
break;
case Instruction::MOVE:
// 实现 move 指令逻辑
ExecuteMove(self, insns, &dex_pc, shadow_frame);
break;
case Instruction::RETURN_VOID:
// 实现返回指令逻辑
return result_register;
case Instruction::INVOKE_VIRTUAL:
// 实现方法调用指令逻辑
ExecuteInvokeVirtual(self, insns, &dex_pc, shadow_frame);
break;
// 其他指令处理...
default:
LOG(FATAL) << "Unsupported opcode: " << opcode;
return JValue();
}
// 检查线程是否被中断
if (UNLIKELY(self->IsExceptionPending())) {
return JValue();
}
}
}
七、ART 源码中的垃圾回收系统
ART 的垃圾回收 (GC) 系统负责自动管理内存,回收不再使用的对象所占用的空间。ART 的 GC 系统在不同版本中不断演进,从 Android 5.0 的 CMS 到 Android 8.0 的 G1,性能不断提升。
7.1 GC 系统架构
ART 的 GC 系统由多个组件组成,包括:
- Heap 类:管理堆内存的分配和回收。
// art/gc/heap.h
class Heap {
public:
// 堆初始化和配置
bool Initialize();
void SetUpZygoteSpace();
// 对象分配
mirror::Object* AllocObject(Thread* self, mirror::Class* klass, size_t byte_count);
mirror::Array* AllocArray(Thread* self, mirror::Class* array_class,
int32_t component_count, size_t component_size);
// GC 触发和执行
void CollectGarbageInternal(GcCause gc_cause, bool clear_soft_references);
void RunGcPhase(GcPhase phase);
// 内存管理
size_t GetHeapSize() const;
size_t GetFreeMemory() const;
size_t GetBytesAllocated() const;
// 其他堆管理方法...
private:
// 堆空间管理
std::vector<gc::Space*> spaces_;
std::vector<gc::Space*> zygote_spaces_;
// GC 收集器
std::vector<std::unique_ptr<gc::collector::Collector>> collectors_;
// 分配器
std::unique_ptr<gc::Allocator> allocator_;
// 其他堆状态和配置...
};
- Collector 类:定义 GC 收集器的接口。
// art/gc/collector/collector.h
class Collector {
public:
// 收集器类型
enum Type {
kCopying,
kMarkSweep,
kCMS,
kG1,
// 其他类型...
};
// 构造函数和析构函数
explicit Collector(Heap* heap, const std::string& name, Type type);
virtual ~Collector();
// GC 执行方法
virtual void Run(GcCause gc_cause, bool clear_soft_references) = 0;
virtual void PreGcSetup() = 0;
virtual void PostGcTeardown() = 0;
// 内存统计
virtual size_t GetBytesFreed() const = 0;
virtual size_t GetObjectsFreed() const = 0;
// 其他收集器方法...
protected:
// 堆引用和收集器名称
Heap* const heap_;
const std::string name_;
const Type type_;
// GC 性能统计
GcStats* stats_;
// 其他收集器状态...
};
- Space 类:管理堆中的不同内存空间。
// art/gc/space/space.h
class Space {
public:
// 空间类型
enum SpaceType {
kSpaceTypeImageSpace,
kSpaceTypeZygoteSpace,
kSpaceTypeAllocationSpace,
kSpaceTypeLargeObjectSpace,
// 其他类型...
};
// 构造函数和析构函数
Space(const std::string& name, SpaceType type, byte* begin, byte* end);
virtual ~Space();
// 空间属性
SpaceType GetType() const { return type_; }
const std::string& GetName() const { return name_; }
byte* Begin() const { return begin_; }
byte* End() const { return end_; }
// 对象遍历
virtual void IterateObjects(mirror::ObjectVisitor* visitor) = 0;
// 其他空间方法...
protected:
// 空间名称和类型
const std::string name_;
const SpaceType type_;
// 空间边界
byte* const begin_;
byte* const end_;
// 其他空间状态...
};
7.2 G1 垃圾回收器实现
Android 8.0 引入了 G1 (Garbage-First) 垃圾回收器,它将堆内存划分为多个区域 (Region),并根据垃圾分布情况优先回收垃圾较多的区域。
// art/gc/collector/g1_collector.h
class G1Collector : public ConcurrentCollector {
public:
G1Collector(Heap* heap, const std::string& name);
~G1Collector() override;
// 实现 Collector 接口
void Run(GcCause gc_cause, bool clear_soft_references) override;
void PreGcSetup() override;
void PostGcTeardown() override;
// G1 特定方法
void InitializeRegions();
void SelectCSet();
void EvacuateCSet();
// 其他 G1 方法...
private:
// 区域管理
std::vector<Region*> regions_;
std::vector<Region*> cset_regions_; // 收集集合区域
// 记忆集和卡表
CardTable* card_table_;
std::vector<MemRegion> remembered_sets_;
// 其他 G1 状态和配置...
};
G1 垃圾回收器的工作流程主要包括:
- 初始标记:标记根对象直接引用的对象。
- 并发标记:与应用程序并发执行,标记所有可达对象。
- 最终标记:处理并发阶段产生的增量更新。
- 筛选回收:选择垃圾最多的区域进行回收,将存活对象复制到其他区域。
7.3 GC 触发机制
ART 的 GC 触发机制基于多种因素,包括内存压力、分配失败等。
// art/gc/heap.cc
void Heap::AllocFailure(Thread* self, size_t num_bytes, size_t align,
AllocatorType allocator_type, bool is_tlab) {
// 记录分配失败
RecordAllocFailure(num_bytes);
// 检查是否需要触发 GC
GcCause gc_cause = kGcCauseHeapTrim;
if (num_bytes > GetFreeMemory()) {
gc_cause = kGcCauseAllocFailed;
}
// 触发 GC
CollectGarbageInternal(gc_cause, /* clear_soft_references */ false);
// 再次尝试分配
mirror::Object* result = AllocNonvirtual(self, num_bytes, align, allocator_type, is_tlab);
if (result == nullptr) {
// 分配仍然失败,抛出 OutOfMemoryError
ThrowOutOfMemoryError("Failed to allocate object", num_bytes);
}
return result;
}
当发生分配失败时,ART 会触发 GC 以回收内存。如果 GC 后仍然无法满足分配请求,则会抛出 OutOfMemoryError。
八、ART 源码中的类加载机制
类加载是 Java 运行时的核心功能之一,ART 的类加载机制负责查找、加载和链接 Java 类。
8.1 类加载器架构
ART 的类加载器架构基于 Java 的委派模型,主要包括:
- BootClassLoader:加载 Java 核心类库。
- PathClassLoader:加载应用程序类。
- DexClassLoader:加载外部 DEX 文件。
类加载器的基类是 mirror::ClassLoader
,它定义了类加载的基本接口。
// art/runtime/mirror/class_loader.h
namespace art {
namespace mirror {
class ClassLoader : public Object {
public:
// 加载类的方法
static Class* FindClass(const char* descriptor, Handle<ClassLoader> class_loader,
Thread* self);
// 其他类加载器方法...
private:
// 类加载器的父加载器
HeapReference<ClassLoader> parent_;
// 其他类加载器状态...
};
} // namespace mirror
} // namespace art
8.2 ClassLinker 实现
ClassLinker
类实现了类加载的核心逻辑,包括类的查找、定义和链接。
// art/runtime/class_linker.h
class ClassLinker {
public:
// 查找并加载类
mirror::Class* FindClass(Thread* self, const char* descriptor, Handle<mirror::ClassLoader> class_loader);
// 定义类
mirror::Class* DefineClass(Thread* self, const char* descriptor, Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file, const DexFile::ClassDef& class_def);
// 链接类
bool LinkClass(Thread* self, Handle<mirror::Class> klass);
// 初始化类
bool EnsureInitialized(Thread* self, Handle<mirror::Class> klass, bool can_init, bool defer_init);
// 其他类加载相关方法...
private:
// 类加载锁和缓存
ReaderWriterMutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
ClassTable classes_ GUARDED_BY(lock_);
std::unordered_map<std::string, ClassLoaderData> class_loader_data_ GUARDED_BY(lock_);
// 其他类链接器状态...
};
8.3 类加载流程
类加载的完整流程包括查找、定义、链接和初始化四个主要步骤。
- 查找类:根据类名和类加载器查找类的字节码。
// art/runtime/class_linker.cc
mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
Handle<mirror::ClassLoader> class_loader) {
// 检查类是否已经加载
{
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
mirror::Class* result = LookupClass(descriptor, class_loader.Get());
if (result != nullptr) {
return result;
}
}
// 委派给父加载器
if (class_loader.Get() != nullptr && class_loader.Get()->GetParent() != nullptr) {
return FindClass(self, descriptor, Handle<mirror::ClassLoader>(
self, class_loader.Get()->GetParent()));
}
// 使用当前加载器查找类
std::vector<const DexFile*> dex_files;
if (class_loader.Get() != nullptr) {
class_loader.Get()->GetDexFiles(&dex_files);
} else {
// 使用引导类加载器
GetBootClassPathDexFiles(&dex_files);
}
// 在 DEX 文件中查找类
for (const DexFile* dex_file : dex_files) {
const DexFile::ClassDef* class_def = dex_file->FindClassDef(descriptor);
if (class_def != nullptr) {
return DefineClass(self, descriptor, class_loader, *dex_file, *class_def);
}
}
// 类未找到
return nullptr;
}
- 定义类:将类的字节码转换为运行时表示。
// art/runtime/class_linker.cc
mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor,
Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file, const DexFile::ClassDef& class_def) {
// 分配类对象
mirror::Class* result = AllocClass(self, &dex_file, class_def.class_idx_);
if (result == nullptr) {
return nullptr;
}
// 初始化类对象
InitializeClass(result, &dex_file, class_def);
// 添加到已加载类表
{
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
AddClass(result);
}
return result;
}
- 链接类:解析类的符号引用,分配静态变量空间等。
// art/runtime/class_linker.cc
bool ClassLinker::LinkClass(Thread* self, Handle<mirror::Class> klass) {
// 确保类未被链接
if (klass->IsLinked()) {
return true;
}
// 链接超类
if (klass->GetSuperClass() != nullptr && !LinkClass(self, Handle<mirror::Class>(
self, klass->GetSuperClass()))) {
return false;
}
// 链接接口
for (size_t i = 0; i < klass->GetInterfaces().Size(); ++i) {
mirror::Class* iface = klass->GetInterfaces().Get(i);
if (iface != nullptr && !LinkClass(self, Handle<mirror::Class>(self, iface))) {
return false;
}
}
// 解析类的字段和方法
ResolveClassMembers(self, klass);
// 标记类为已链接
klass->SetLinked(true);
return true;
}
- 初始化类:执行类的静态初始化代码。
// art/runtime/class_linker.cc
bool ClassLinker::EnsureInitialized(Thread* self, Handle<mirror::Class> klass,
bool can_init, bool defer_init) {
// 检查类是否已经初始化
if (klass->IsInitialized()) {
return true;
}
// 检查类是否正在初始化
if (klass->IsInitializing()) {
// 处理循环初始化
if (self->CurrentTransaction() != nullptr &&
self->CurrentTransaction()->IsClassBeingInitialized(klass.Get())) {
return true;
}
// 等待初始化完成
Monitor::ScopedLock sl(self, *klass->GetClassInitLock());
while (klass->IsInitializing()) {
klass->GetClassInitLock()->Wait(self);
}
return klass->IsInitialized();
}
// 开始初始化类
{
Monitor::ScopedLock sl(self, *klass->GetClassInitLock());
if (!klass->IsInitialized() && !klass->IsInitializing()) {
klass->SetInitializing(true);
}
}
// 初始化超类
if (klass->GetSuperClass() != nullptr && !EnsureInitialized(self, Handle<mirror::Class>(
self, klass->GetSuperClass()), can_init, defer_init)) {
FinishClassInitialization(self, klass, false);
return false;
}
// 执行类的静态初始化方法
if (!defer_init) {
bool success = ExecuteClassInitialization(self, klass);
FinishClassInitialization(self, klass, success);
return success;
}
return true;
}
九、ART 源码中的 JNI 实现
Java Native Interface (JNI) 是 Java 平台提供的一种机制,允许 Java 代码与本地代码(如 C、C++)进行交互。ART 的 JNI 实现负责处理 Java 代码与本地代码之间的调用和数据传递。
9.1 JNI 环境与接口
ART 的 JNI 实现主要基于 JNIEnv
和 JavaVM
两个核心接口。
// art/runtime/jni_env.h
struct JNIEnv {
// JNI 函数表指针
const struct JNINativeInterface* functions;
// 构造函数
JNIEnv(const struct JNINativeInterface* func_table) : functions(func_table) {}
// JNI 方法的内联实现
jclass FindClass(const char* name) {
return functions->FindClass(this, name);
}
jobject NewObject(jclass clazz, jmethodID methodID, ...) {
va_list args;
va_start(args, methodID);
jobject result = functions->NewObjectV(this, clazz, methodID, args);
va_end(args);
return result;
}
// 其他 JNI 方法...
};
// art/runtime/java_vm.h
struct JavaVM {
// JNI 虚拟机函数表指针
const struct JNIInvokeInterface* functions;
// 构造函数
JavaVM(const struct JNIInvokeInterface* func_table) : functions(func_table) {}
// JNI 虚拟机方法的内联实现
jint GetEnv(void** env, jint version) {
return functions->GetEnv(this, env, version);
}
jint AttachCurrentThread(JavaVMAttachArgs* args, void** env) {
return functions->AttachCurrentThread(this, args, env);
}
// 其他 JNI 虚拟机方法...
};
9.2 JNI 注册机制
ART 支持静态和动态两种 JNI 注册方式。
- 静态注册:通过方法名和签名自动映射到本地函数。
// art/runtime/jni_internal.h
// 静态注册的本地方法实现示例
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_MyClass_get
十、ART 源码中的线程管理机制
线程管理是 ART 运行时的重要组成部分,它确保多线程应用程序能够正确、高效地执行。ART 的线程管理机制涉及线程的创建、调度、同步以及与 Java 线程模型的映射等多个方面。
10.1 线程数据结构
在 ART 中,Thread
类是线程管理的核心数据结构,定义于 art/runtime/thread.h
文件。它封装了线程运行时的各种状态和资源。
// art/runtime/thread.h
class Thread : public StackVisitor::Callback {
public:
// 线程状态枚举
enum State {
kRunnable,
kBlocked,
kWaiting,
kTimedWaiting,
kTerminated,
kInitializing,
kSuspended
};
// 线程 ID
int32_t GetTid() const { return tid_; }
// 获取线程状态
State GetState() const { return state_; }
// 获取运行时实例
Runtime* GetRuntime() const { return runtime_; }
// 获取线程名称
const char* GetThreadName() const { return thread_name_.c_str(); }
// 设置线程状态
void SetState(State new_state) { state_ = new_state; }
// 设置运行时
void SetRuntime(Runtime* runtime) { runtime_ = runtime; }
// 线程局部存储 (TLS) 相关操作
void* GetTls() const { return tls_; }
void SetTls(void* value) { tls_ = value; }
// 同步相关操作,如获取和释放锁
void AcquireLock(Lock* lock) { lock->Acquire(this); }
void ReleaseLock(Lock* lock) { lock->Release(this); }
// 与 JNI 相关的操作
JNIEnv* GetJniEnv() { return jni_env_.get(); }
private:
// 线程 ID
int32_t tid_;
// 线程状态
State state_;
// 指向运行时的指针
Runtime* runtime_;
// 线程名称
std::string thread_name_;
// 线程局部存储
void* tls_;
// JNI 环境
std::unique_ptr<JNIEnvExt> jni_env_;
// 其他线程相关的状态和资源...
};
Thread
类通过成员变量记录线程的关键信息,如线程 ID、状态、所属运行时等。同时提供一系列方法,方便对线程状态进行查询和修改,以及进行同步、JNI 交互等操作 。
10.2 线程创建与启动
ART 中创建和启动线程主要涉及 Java 层 Thread
类与底层 art::Thread
类的协作。当在 Java 代码中调用 new Thread()
创建线程对象并调用 start()
方法时,会触发底层的线程创建逻辑。
// art/runtime/thread.cc
void Thread::CreateNativeThread(JNIEnv* env, jobject java_thread, ThreadStartRunnable* runnable) {
// 创建线程属性
pthread_attr_t attr;
pthread_attr_init(&attr);
// 设置线程分离状态等属性
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// 实际创建线程的函数指针
void* (*start_routine)(void*) = &Thread::ThreadStart;
int result = pthread_create(&tid_, &attr, start_routine, runnable);
if (result != 0) {
// 处理线程创建失败的情况
LOG(ERROR) << "Failed to create native thread: " << strerror(result);
}
pthread_attr_destroy(&attr);
}
void* Thread::ThreadStart(void* args) {
ThreadStartRunnable* runnable = static_cast<ThreadStartRunnable*>(args);
// 初始化线程环境
Thread* self = Thread::Current();
self->SetState(kRunnable);
// 执行线程任务
runnable->Run();
// 线程任务完成后的清理工作
self->SetState(kTerminated);
delete runnable;
return nullptr;
}
CreateNativeThread
函数利用 POSIX 线程库 pthread
创建底层线程,设置线程属性并指定线程入口函数 ThreadStart
。ThreadStart
函数则负责初始化线程状态,执行传入的线程任务,在任务完成后清理资源并更新线程状态为终止。
10.3 线程同步机制
ART 提供了多种线程同步机制,以保证多线程环境下数据的一致性和正确性,其中最常用的是监视器(Monitor)和锁(Lock)机制 。
// art/runtime/monitor.h
class Monitor {
public:
// 进入监视器,获取锁
void Enter(Thread* self) {
pthread_mutex_lock(&mutex_);
while (IsLocked()) {
// 如果锁已被占用,线程等待
pthread_cond_wait(&cond_, &mutex_);
}
// 设置锁的持有者为当前线程
lock_owner_ = self;
}
// 退出监视器,释放锁
void Exit(Thread* self) {
if (lock_owner_ != self) {
// 检查锁的持有者是否为当前线程
LOG(ERROR) << "Thread is not the owner of the monitor";
return;
}
lock_owner_ = nullptr;
// 唤醒等待在该监视器上的一个线程
pthread_cond_signal(&cond_);
pthread_mutex_unlock(&mutex_);
}
// 判断监视器是否已被锁定
bool IsLocked() const { return lock_owner_ != nullptr; }
private:
// 互斥锁
pthread_mutex_t mutex_;
// 条件变量
pthread_cond_t cond_;
// 锁的持有者
Thread* lock_owner_;
};
Monitor
类通过 pthread_mutex_t
实现互斥锁,通过 pthread_cond_t
实现条件变量。Enter
方法尝试获取锁,如果锁已被占用,线程将等待;Exit
方法释放锁并唤醒一个等待线程。这种机制与 Java 中的 synchronized
关键字相对应,确保同一时间只有一个线程能够访问被监视器保护的代码块。
10.4 线程调度与优先级
ART 的线程调度依赖于底层操作系统的线程调度机制,同时也会考虑 Java 线程的优先级。在 Android 系统中,底层使用 Linux 的 CFS(完全公平调度器)等调度算法。
// art/runtime/thread.cc
// 设置线程优先级的方法
void Thread::SetPriority(int priority) {
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &policy, ¶m);
// 根据 Java 优先级映射到 Linux 优先级
switch (priority) {
case Thread::MIN_PRIORITY:
param.sched_priority = sched_get_priority_min(SCHED_OTHER);
break;
case Thread::NORM_PRIORITY:
param.sched_priority = (sched_get_priority_max(SCHED_OTHER) + sched_get_priority_min(SCHED_OTHER)) / 2;
break;
case Thread::MAX_PRIORITY:
param.sched_priority = sched_get_priority_max(SCHED_OTHER);
break;
default:
break;
}
pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m);
}
SetPriority
方法将 Java 线程的优先级(MIN_PRIORITY
、NORM_PRIORITY
、MAX_PRIORITY
等)映射为 Linux 系统的线程优先级,并通过 pthread_setschedparam
函数设置线程的调度参数,从而影响线程在系统中的调度优先级。
十一、ART 源码中的调试与性能分析机制
调试和性能分析对于理解和优化 ART 运行时以及基于其运行的应用程序至关重要。ART 提供了丰富的调试接口和性能分析工具支持,这些功能在源码层面有着复杂且精细的实现。
11.1 调试接口实现
ART 实现了多种调试接口,其中 JDWP(Java Debug Wire Protocol)是最常用的调试协议,用于支持 Java 应用程序的远程调试。相关实现主要位于 art/debug/jdwp
目录。
// art/debug/jdwp/jdwp_agent.cc
class JdwpAgent {
public:
// 初始化 JDWP 代理
bool Initialize() {
// 创建并初始化 JDWP 连接
connection_ = std::make_unique<JdwpConnection>();
if (!connection_->Initialize()) {
LOG(ERROR) << "Failed to initialize JDWP connection";
return false;
}
// 启动监听线程
listening_thread_ = std::thread(&JdwpAgent::ListenForDebugger, this);
return true;
}
// 监听调试器连接
void ListenForDebugger() {
while (true) {
if (connection_->ListenOnPort(8700)) {
// 接受调试器连接
std::unique_ptr<JdwpConnection> client_connection = connection_->Accept();
if (client_connection != nullptr) {
// 处理调试请求
HandleDebuggerConnection(std::move(client_connection));
}
} else {
LOG(ERROR) << "Failed to listen on JDWP port";
}
}
}
// 处理调试器连接
void HandleDebuggerConnection(std::unique_ptr<JdwpConnection> client_connection) {
JdwpHandler handler(std::move(client_connection));
handler.HandleRequests();
}
private:
// JDWP 连接对象
std::unique_ptr<JdwpConnection> connection_;
// 监听线程
std::thread listening_thread_;
};
JdwpAgent
类负责初始化 JDWP 代理,通过 JdwpConnection
类建立与调试器的连接,监听指定端口(默认为 8700),接受调试器连接请求,并将连接交给 JdwpHandler
处理具体的调试请求,如设置断点、查看变量值等操作。
11.2 性能分析工具集成
ART 与 Perfetto 等性能分析工具深度集成,以便对应用程序的性能进行详细分析。相关代码位于 art/tools/perfetto
目录。
// art/tools/perfetto/art_perfetto_producer.cc
class ArtPerfettoProducer : public perfetto::DataSource {
public:
// 初始化生产者
void Initialize() {
// 注册数据源
perfetto::Tracing::RegisterDataSource(this, "art.runtime");
}
// 激活数据源,开始收集数据
void OnActivate(const perfetto::DataSourceConfig& config) override {
is_active_ = true;
// 根据配置设置采样间隔等参数
sampling_interval_ms_ = config.sampling_interval_ms();
StartCollectingData();
}
// 停止数据源,停止数据收集
void OnDeactivate() override {
is_active_ = false;
}
// 收集性能数据
void CollectData(perfetto::TraceWriter* writer) override {
// 收集线程相关数据
CollectThreadData(writer);
// 收集垃圾回收相关数据
CollectGcData(writer);
// 收集方法调用相关数据
CollectMethodInvocationData(writer);
}
private:
// 收集线程数据
void CollectThreadData(perfetto::TraceWriter* writer) {
auto* thread_list = ThreadList::Current();
for (Thread* thread : *thread_list) {
auto* thread_event = writer->NewTracePacket()->SetThread();
thread_event->set_tid(thread->GetTid());
thread_event->set_name(thread->GetThreadName());
thread_event->set_state(static_cast<int>(thread->GetState()));
}
}
// 收集垃圾回收数据
void CollectGcData(perfetto::TraceWriter* writer) {
Heap* heap = Runtime::Current()->GetHeap();
auto* gc_event = writer->NewTracePacket()->SetGcEvent();
gc_event->set_heap_size(heap->GetHeapSize());
gc_event->set_free_memory(heap->GetFreeMemory());
gc_event->set_num_gc_runs(heap->GetGcStats()->GetTotalGcCount());
}
// 收集方法调用数据
void CollectMethodInvocationData(perfetto::TraceWriter* writer) {
// 遍历方法调用记录,收集调用次数、执行时间等数据
MethodProfiler* profiler = MethodProfiler::GetInstance();
const auto& method_stats = profiler->GetMethodStats();
for (const auto& [method, stats] : method_stats) {
auto* method_event = writer->NewTracePacket()->SetMethodInvocation();
method_event->set_method_name(method->GetName());
method_event->set_class_name(method->GetDeclaringClass()->GetName());
method_event->set_call_count(stats.call_count);
method_event->set_total_time_ns(stats.total_time_ns);
}
}
// 启动数据收集线程
void StartCollectingData() {
collecting_thread_ = std::thread([this]() {
while (is_active_) {
perfetto::TraceWriter writer;
CollectData(&writer);
std::this_thread::sleep_for(std::chrono::milliseconds(sampling_interval_ms_));
}
});
}
bool is_active_ = false;
uint32_t sampling_interval_ms_ = 1000;
std::thread collecting_thread_;
};
ArtPerfettoProducer
类实现了 perfetto::DataSource
接口,在初始化时注册数据源。激活后,按照设定的采样间隔,定期收集线程状态、垃圾回收信息、方法调用等性能数据,并通过 perfetto::TraceWriter
将数据写入性能分析工具,供开发者分析应用程序的性能瓶颈。
11.3 日志与诊断工具
ART 内置了强大的日志系统,用于记录运行时的各种信息,帮助开发者诊断问题。日志相关代码主要在 art/base/logging.h
和 art/base/logging.cc
中。
// art/base/logging.cc
// 日志级别枚举
enum class LogSeverity {
kError,
kWarning,
kInfo,
kDebug
};
// 输出日志的通用函数
void Log(LogSeverity severity, const char* tag, const char* format, ...) {
va_list args;
va_start(args, format);
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
const char* severity_str;
switch (severity) {
case LogSeverity::kError:
severity_str = "ERROR";
break;
case LogSeverity::kWarning:
severity_str = "WARNING";
break;
case LogSeverity::kInfo:
severity_str = "INFO";
break;
case LogSeverity::kDebug:
severity_str = "DEBUG";
break;
}
// 输出日志到标准错误输出或其他日志系统
fprintf(stderr, "[%s][%s] %s\n", severity_str, tag, buffer);
}
Log
函数根据不同的日志级别(错误、警告、信息、调试),将格式化后的日志信息输出到标准错误输出或其他日志系统中。开发者可以通过设置日志级别,灵活控制运行时输出的日志内容,方便定位和解决问题 。
十二、ART 与 Android 系统其他模块的交互机制
ART 并非孤立运行,而是与 Android 系统的众多模块紧密协作,共同为应用程序提供运行环境。这种交互涉及进程管理、系统服务调用、硬件资源访问等多个方面。
12.1 与进程管理模块的交互
在 Android 系统中,Zygote 进程是应用进程的孵化器,ART 在 Zygote 进程的启动和应用进程的创建过程中发挥关键作用。
// art/runtime/zygote.cc
// Zygote 进程初始化 ART
void ZygoteInit() {
// 创建 ART 运行时实例
Runtime* runtime = Runtime::Create();
if (runtime == nullptr) {
LOG(ERROR) << "Failed to create ART runtime in Zygote";
return;
}
// 预加载核心类和资源
PreloadClasses();
PreloadResources();
// 启动 Zygote 服务器,等待应用进程创建请求
StartZygoteServer();
}
// 处理应用进程创建请求
void ZygoteForkAndSpecialize(const std::vector<std::string>& args) {
// 复制 Zygote 进程
pid_t pid = fork();
if (pid == 0) {
// 在子进程(新应用进程)中
// 初始化应用进程的 ART 环境
InitializeApplicationRuntime();
// 执行应用进程的初始化逻辑
ExecuteApplication(args);
} else if (pid > 0) {
// 在 Zygote 进程中,处理子进程状态
MonitorChildProcess(pid);
} else {
十三、ART 中的安全机制实现
在移动计算环境下,安全是 Android 系统至关重要的部分,ART 作为应用程序运行的核心,实现了多种安全机制,保障应用程序运行的安全性和数据的完整性。
13.1 字节码验证机制
ART 的字节码验证在 art/verifier
目录中实现,用于确保 DEX 文件中的字节码符合 Java 语言规范和安全要求,防止恶意代码执行非法操作。
// art/verifier/dex_verifier.cc
bool DexVerifier::Verify() {
// 验证文件头和基本结构
if (!VerifyHeader()) {
return false;
}
// 遍历类定义,验证每个类
for (size_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
const DexFile::ClassDef& class_def = dex_file_->GetClassDef(i);
if (!VerifyClass(class_def)) {
return false;
}
}
return true;
}
bool DexVerifier::VerifyHeader() {
// 检查 DEX 文件魔数,确保文件格式正确
if (memcmp(dex_file_->Begin(), "dex\n035\0", 8) != 0) {
LOG(ERROR) << "Invalid DEX file magic number";
return false;
}
// 验证文件校验和和签名
if (dex_file_->Checksum() != CalculateChecksum()) {
LOG(ERROR) << "DEX file checksum mismatch";
return false;
}
return true;
}
bool DexVerifier::VerifyClass(const DexFile::ClassDef& class_def) {
// 验证类的访问标志,确保合法
if ((class_def.access_flags_ & ~kValidClassAccessFlags) != 0) {
LOG(ERROR) << "Invalid class access flags";
return false;
}
// 验证类的继承关系,防止循环继承
if (!VerifyClassInheritance(class_def)) {
return false;
}
// 遍历类的字段和方法,进行验证
for (size_t j = 0; j < class_def.fields_size_; ++j) {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(class_def.fields_off_ + j);
if (!VerifyField(field_id)) {
return false;
}
}
for (size_t j = 0; j < class_def.methods_size_; ++j) {
const DexFile::MethodId& method_id = dex_file_->GetMethodId(class_def.methods_off_ + j);
if (!VerifyMethod(method_id)) {
return false;
}
}
return true;
}
bool DexVerifier::VerifyMethod(const DexFile::MethodId& method_id) {
// 获取方法的字节码
const DexFile::CodeItem* code_item = dex_file_->GetCodeItem(method_id);
if (code_item == nullptr) {
return true; // 抽象方法或 native 方法无需验证字节码
}
// 验证字节码指令,确保操作数栈和局部变量表使用合法
StackState stack_state;
LocalVariables local_vars;
for (uint32_t pc = 0; pc < code_item->insns_size_in_code_units_; ++pc) {
const uint16_t opcode = DecodeOpcode(code_item->insns_[pc]);
if (!VerifyInstruction(opcode, &stack_state, &local_vars)) {
return false;
}
}
return true;
}
DexVerifier
类首先验证 DEX 文件的头部信息,确保文件格式正确和完整性。接着对每个类进行验证,包括访问标志、继承关系、字段和方法。对于方法,进一步验证字节码指令,检查操作数栈和局部变量表的使用是否符合规范,防止非法内存访问、类型转换错误等安全问题。
13.2 内存隔离与保护
ART 通过内存管理机制实现不同应用程序之间的内存隔离,避免应用之间的数据泄露和恶意访问。
// art/gc/heap.cc
mirror::Object* Heap::AllocObject(Thread* self, mirror::Class* klass, size_t byte_count) {
// 根据对象大小选择合适的分配空间
gc::Space* space = SelectAllocSpace(byte_count);
if (space == nullptr) {
// 内存不足,触发垃圾回收
CollectGarbageInternal(kGcCauseAlloc, false);
space = SelectAllocSpace(byte_count);
if (space == nullptr) {
// 回收后仍不足,抛出 OOM 异常
ThrowOutOfMemoryError(self, "Failed to allocate object", byte_count);
return nullptr;
}
}
// 在选定的空间中分配对象
mirror::Object* obj = space->AllocObject(self, klass, byte_count);
if (obj == nullptr) {
// 分配失败处理
LOG(ERROR) << "Failed to allocate object in space";
}
return obj;
}
gc::Space* Heap::SelectAllocSpace(size_t byte_count) {
// 小对象分配到分配空间
if (byte_count <= kMaxSmallObjectSize) {
return allocation_space_;
}
// 大对象分配到大对象空间
return large_object_space_;
}
在对象分配时,ART 根据对象大小将其分配到不同的内存空间,如小对象空间和大对象空间。每个应用程序运行在独立的进程中,拥有自己的堆内存区域,不同进程之间的内存相互隔离。同时,通过垃圾回收机制,及时回收不再使用的内存,确保内存使用的安全性和高效性。
13.3 权限控制与安全上下文
ART 在执行应用程序时,结合 Android 系统的权限机制,确保应用程序只能访问被授权的资源。
// art/runtime/jni_internal.cc
extern "C" JNIEXPORT jobject JNICALL
Java_android_os_Environment_getExternalStorageDirectory(JNIEnv* env, jclass clazz) {
// 检查应用是否具有外部存储访问权限
if (!CheckPermission(env, "android.permission.WRITE_EXTERNAL_STORAGE")) {
ThrowSecurityException(env, "Permission denied");
return nullptr;
}
// 获取外部存储目录路径
const char* path = GetExternalStoragePath();
if (path == nullptr) {
// 路径获取失败处理
ThrowIOException(env, "Failed to get external storage path");
return nullptr;
}
// 创建并返回 Java 字符串对象
return env->NewStringUTF(path);
}
bool CheckPermission(JNIEnv* env, const char* permission) {
// 获取当前应用的安全上下文
SecurityContext* security_context = GetCurrentSecurityContext();
if (security_context == nullptr) {
return false;
}
// 检查安全上下文中是否包含指定权限
return security_context->HasPermission(permission);
}
当应用程序通过 JNI 调用访问系统资源的方法时,ART 会检查应用程序的安全上下文,验证其是否具有相应的权限。只有在权限验证通过的情况下,才允许应用程序执行相关操作,否则抛出安全异常,阻止非法访问,从而保障系统和用户数据的安全。
十四、ART 源码中的动态加载与插件化支持
随着移动应用功能的日益复杂,动态加载和插件化技术成为提升应用灵活性和扩展性的重要手段。ART 在源码层面为动态加载和插件化提供了底层支持。
14.1 动态类加载机制扩展
除了常规的类加载流程,ART 支持在运行时动态加载额外的类文件或 DEX 文件。
// art/runtime/class_loader.cc
mirror::Class* ClassLoader::LoadClassFromDexFile(Thread* self, const char* dex_file_path, const char* class_descriptor) {
// 打开 DEX 文件
std::unique_ptr<const DexFile> dex_file = OpenDexFile(dex_file_path);
if (dex_file == nullptr) {
LOG(ERROR) << "Failed to open DEX file: " << dex_file_path;
return nullptr;
}
// 在 DEX 文件中查找类定义
const DexFile::ClassDef* class_def = dex_file->FindClassDef(class_descriptor);
if (class_def == nullptr) {
LOG(ERROR) << "Class not found in DEX file: " << class_descriptor;
return nullptr;
}
// 定义并加载类
return DefineClass(self, class_descriptor, this, *dex_file, *class_def);
}
std::unique_ptr<const DexFile> OpenDexFile(const char* path) {
std::string error_msg;
// 使用 DEX 文件加载器打开文件
return std::unique_ptr<const DexFile>(DexFileLoader().Open(path, path, false, false, &error_msg));
}
ClassLoader
类通过 LoadClassFromDexFile
方法,允许在运行时指定 DEX 文件路径和类描述符,动态加载类。该方法首先打开 DEX 文件,查找类定义,然后通过 DefineClass
方法将类加载到运行时环境中,为插件化中动态加载新的功能模块提供了基础。
14.2 插件化的运行时支持
在插件化场景下,ART 需要处理插件与主应用之间的资源隔离、类加载冲突等问题。
// art/runtime/plugin_manager.cc
class PluginManager {
public:
PluginManager() {
// 初始化插件列表和类加载器映射
plugins_.clear();
class_loader_mapping_.clear();
}
// 加载插件
bool LoadPlugin(const char* plugin_path) {
std::unique_ptr<Plugin> plugin = std::make_unique<Plugin>(plugin_path);
if (!plugin->Initialize()) {
LOG(ERROR) << "Failed to initialize plugin: " << plugin_path;
return false;
}
// 为插件创建独立的类加载器
std::unique_ptr<ClassLoader> class_loader = std::make_unique<PluginClassLoader>(plugin.get());
plugin->SetClassLoader(std::move(class_loader));
// 添加插件到管理器
plugins_.push_back(std::move(plugin));
class_loader_mapping_[plugin.get()] = plugin->GetClassLoader();
return true;
}
// 获取插件中的类加载器
ClassLoader* GetClassLoaderForPlugin(Plugin* plugin) {
auto it = class_loader_mapping_.find(plugin);
if (it != class_loader_mapping_.end()) {
return it->second;
}
return nullptr;
}
private:
// 插件列表
std::vector<std::unique_ptr<Plugin>> plugins_;
// 插件与类加载器的映射
std::unordered_map<Plugin*, ClassLoader*> class_loader_mapping_;
};
class Plugin {
public:
Plugin(const char* path) : path_(path) {}
bool Initialize() {
// 解析插件中的 DEX 文件和资源
if (!ParseDexFiles()) {
return false;
}
if (!LoadResources()) {
return false;
}
return true;
}
ClassLoader* GetClassLoader() { return class_loader_.get(); }
void SetClassLoader(std::unique_ptr<ClassLoader> loader) { class_loader_ = std::move(loader); }
private:
std::string path_;
std::vector<std::unique_ptr<const DexFile>> dex_files_;
std::unique_ptr<ClassLoader> class_loader_;
bool ParseDexFiles() {
// 读取插件中的 DEX 文件
// 省略具体实现
return true;
}
bool LoadResources() {
// 加载插件资源
// 省略具体实现
return true;
}
};
PluginManager
类负责管理插件的加载,为每个插件创建独立的类加载器,避免类加载冲突。Plugin
类则处理插件内部的 DEX 文件解析和资源加载。通过这种方式,ART 支持在运行时动态加载插件,实现应用功能的扩展,同时保证插件与主应用以及不同插件之间的隔离性。
14.3 动态链接与方法调用
当动态加载类后,ART 需要处理类中方法的动态链接和调用。
// art/runtime/dynamic_method_invoke.cc
jobject DynamicInvokeMethod(JNIEnv* env, jobject obj, const char* method_name, const char* method_signature, ...) {
// 获取类的 Class 对象
jclass clazz = env->GetObjectClass(obj);
if (clazz == nullptr) {
LOG(ERROR) << "Failed to get class for object";
return nullptr;
}
// 查找方法 ID
jmethodID method_id = env->GetMethodID(clazz, method_name, method_signature);
if (method_id == nullptr) {
LOG(ERROR) << "Method not found: " << method_name << " " << method_signature;
return nullptr;
}
// 处理方法调用参数
va_list args;
va_start(args, method_signature);
jobject result = env->CallObjectMethodV(obj, method_id, args);
va_end(args);
return result;
}
DynamicInvokeMethod
函数通过 JNI 接口,在运行时动态获取类的方法 ID,并调用方法。这种机制使得在动态加载类后,能够正常执行类中的方法,满足插件化和动态加载场景下的功能需求,实现应用功能的动态扩展和灵活调用。
十五、ART 在不同 Android 版本中的演进与变化
随着 Android 系统的不断更新迭代,ART 也在持续优化和改进,以适应新的硬件特性、提升性能和增强安全性。
15.1 从 Dalvik 到 ART 的转变(Android 5.0)
在 Android 5.0 之前,Dalvik 虚拟机是 Android 应用的运行环境。Dalvik 使用 JIT(即时编译)技术,在应用运行时将字节码转换为机器码执行。而 ART 采用 AOT(提前编译)技术,在应用安装阶段就将字节码编译为机器码。
// 对比 Dalvik 和 ART 的编译流程差异示意
// Dalvik 的 JIT 编译示例(简化示意)
void* DalvikJitCompile(const uint8_t* bytecode, size_t bytecode_size) {
// 解析字节码
// 生成中间表示
// 优化中间表示
// 生成机器码
// 省略具体实现
return nullptr;
}
// ART 的 AOT 编译示例(简化示意)
void ArtAotCompile(const char* dex_file_path, const char* oat_file_path) {
// 读取 DEX 文件
std::unique_ptr<const DexFile> dex_file = OpenDexFile(dex_file_path);
if (dex_file == nullptr) {
return;
}
// 创建编译驱动
std::unique_ptr<CompilationDriver> driver = std::make_unique<CompilationDriver>();
// 执行编译
std::unique_ptr<const OatFile> oat_file = driver->Compile(dex_file.get());
if (oat_file == nullptr) {
return;
}
// 写入 OAT 文件
WriteOatFile(oat_file_path, *oat_file);
}
这种转变使得应用启动速度大幅提升,执行效率提高,同时降低了 CPU 占用。但 AOT 编译也带来了应用安装时间变长、占用存储空间增加等问题,后续版本中 ART 不断对此进行优化。
15.2 Android 6.0 中的优化
在 Android 6.0 中,ART 对垃圾回收机制进行了改进,引入了并发标记 - 清除(Concurrent Mark Sweep,CMS)垃圾回收器的优化版本。
// art/gc/collector/cms_collector.cc
class CmsCollector : public Collector {
public:
CmsCollector(Heap* heap) : Collector(heap, "CMS") {
// 初始化并发标记线程等
concurrent_mark_thread_ = std::thread(&CmsCollector::ConcurrentMark, this);
}
~CmsCollector() {
// 停止并发标记线程
concurrent_mark_thread_.join();
}
void Run(GcCause gc_cause, bool clear_soft_references) override {
// 初始标记阶段
StopTheWorldMark();
// 并发标记阶段
// 由并发标记线程执行
// 重新标记阶段
StopTheWorldRemark();
// 清除阶段
Sweep();
}
private:
std::thread concurrent_mark_thread_;
void ConcurrentMark() {
// 并发标记对象
// 处理对象引用变化
// 省略具体实现
}
};
改进后的 CMS 垃圾回收器减少了垃圾回收过程中应用程序的暂停时间,提升了应用的流畅度和响应性。同时,对内存分配策略也进行了优化,提高了内存使用效率。
15.3 Android 8.0 引入 G1 垃圾回收器
Android 8.0 引入了 G1(Garbage - First)垃圾回收器,取代了之前的 CMS 垃圾回收器。G1 将堆内存划分为多个大小相等的 Region,采用分代收集和增量回收策略。
// art/gc/collector/g1_collector.cc
class G1Collector : public Collector {
public
十六、ART 中的即时编译(JIT)优化进阶
ART的即时编译(JIT)功能在提升应用运行时性能方面发挥着重要作用,随着版本演进,其优化策略和实现细节不断丰富。
16.1 JIT 编译触发条件细化
JIT编译并非对所有方法一视同仁,而是依据特定条件判断是否对方法进行编译。在ART源码中,触发JIT编译的条件判断逻辑复杂且精细。
// art/jit/profiler.cc
void Profiler::SampleMethod(ArtMethod* method) {
// 更新方法执行计数器
std::lock_guard<std::mutex> lock(mutex_);
MethodData* data = GetMethodData(method);
if (data != nullptr) {
data->increment_sample_count();
// 检查是否达到编译阈值,这里的阈值并非固定,会根据系统负载等因素动态调整
if (data->sample_count() >= CalculateJitThreshold()) {
RequestCompilation(method);
}
}
}
uint32_t Profiler::CalculateJitThreshold() {
// 获取系统当前负载情况
float systemLoad = GetSystemLoad();
// 根据负载动态调整JIT编译阈值,负载越高,阈值越高,减少不必要的编译开销
if (systemLoad > 0.8) {
return high_load_jit_threshold_;
} else if (systemLoad > 0.5) {
return medium_load_jit_threshold_;
} else {
return low_load_jit_threshold_;
}
}
上述代码展示了方法采样和JIT编译触发的部分逻辑。Profiler::SampleMethod
函数在每次方法被调用时更新调用计数,当计数达到通过CalculateJitThreshold
计算出的阈值时,触发JIT编译请求。CalculateJitThreshold
函数根据系统负载动态调整阈值,实现编译资源的合理分配,避免在系统繁忙时进行过多编译操作影响性能。
16.2 JIT 编译优化策略增强
JIT编译过程中采用了多种优化策略,除了常见的内联、常量传播等,还引入了更复杂的优化手段。
// art/jit/optimizing_jit_compiler.cc
void OptimizingJitCompiler::RunAdvancedOptimizations(HGraph* graph, CompilationUnit* cu) {
// 执行逃逸分析,判断对象是否会在方法外被访问
PerformEscapeAnalysis(graph, cu);
// 根据逃逸分析结果,进行锁消除优化,如果对象仅在当前方法内使用,可消除不必要的锁操作
EliminateLocksBasedOnEscapeAnalysis(graph, cu);
// 进行循环优化,包括循环展开、循环不变量外提等
OptimizeLoops(graph, cu);
}
void OptimizingJitCompiler::PerformEscapeAnalysis(HGraph* graph, CompilationUnit* cu) {
// 遍历图中的节点,分析对象的生命周期和引用关系
for (HInstruction* instruction : graph->GetInstructions()) {
if (instruction->IsObjectAllocation()) {
HAllocationNode* allocation_node = static_cast<HAllocationNode*>(instruction);
// 追踪对象的引用路径,判断是否会逃逸出当前方法
if (!IsObjectEscaping(allocation_node)) {
allocation_node->SetNonEscaping();
}
}
}
}
OptimizingJitCompiler::RunAdvancedOptimizations
函数展示了高级优化策略的执行流程。通过逃逸分析判断对象是否会在方法外被访问,进而进行锁消除优化,减少不必要的同步开销;同时对循环结构进行深度优化,提升循环执行效率。这些优化策略相互配合,使JIT编译后的代码性能得到显著提升。
16.3 JIT 与 AOT 协同工作机制
ART中JIT和AOT并非相互独立,而是协同工作以达到最佳性能。在应用运行初期,AOT编译的代码提供基础执行效率,随着应用运行,JIT对热点方法进一步优化。
// art/runtime/runtime.cc
void Runtime::HandleMethodInvocation(ArtMethod* method) {
// 检查方法是否已被AOT编译
if (method->IsAotCompiled()) {
// 直接执行AOT编译后的代码
ExecuteAotCode(method);
} else {
// 未被AOT编译,使用解释器执行,并启动JIT编译监控
InterpretMethod(method);
profiler_->SampleMethod(method);
}
}
void Runtime::ExecuteAotCode(ArtMethod* method) {
// 执行AOT编译后的机器码
void* entry_point = method->GetAotEntryPoint();
((void(*)())entry_point)();
}
Runtime::HandleMethodInvocation
函数体现了JIT与AOT的协同逻辑。当方法被调用时,先判断是否存在AOT编译的代码,若有则直接执行;若无则通过解释器执行,并由profiler_
对方法进行采样,一旦满足JIT编译条件,即对方法进行JIT编译,实现运行时性能的动态优化。
十七、ART 与硬件抽象层(HAL)的交互细节
ART与硬件抽象层(HAL)的交互是实现应用与底层硬件通信的关键环节,其交互过程涉及多个方面的细节处理。
17.1 图形硬件加速交互
在图形渲染方面,ART通过与HAL交互实现硬件加速。以OpenGL ES接口调用为例,ART将Java层的图形绘制请求转换为对HAL中图形驱动的调用。
// art/runtime/jni/android_opengl_JNIGraphicsJNI.cc
extern "C" JNIEXPORT void JNICALL
Java_android_opengl_GLSurfaceView_00024Egl_nOnSurfaceCreated(JNIEnv* env, jobject thiz, jobject surface, jobject context) {
// 获取EGLDisplay和EGLSurface等图形上下文对象
EGLDisplay display = eglGetCurrentDisplay();
EGLSurface egl_surface = eglCreateWindowSurface(display, egl_config, surface, nullptr);
// 通过HAL接口初始化图形硬件设备
InitializeGraphicsHardware(egl_surface);
// 其他初始化操作
}
void InitializeGraphicsHardware(EGLSurface surface) {
// 获取HAL图形设备实例
GraphicsHardware* graphics_hardware = GetGraphicsHardwareInstance();
if (graphics_hardware!= nullptr) {
// 调用HAL设备的初始化函数
graphics_hardware->Initialize(surface);
}
}
上述代码展示了Java层GLSurfaceView
创建时与HAL的交互流程。通过JNI调用,获取图形上下文对象,进而通过InitializeGraphicsHardware
函数获取HAL图形设备实例并进行初始化,将Java层的图形绘制请求传递给底层硬件,实现高效的图形渲染。
17.2 传感器数据获取交互
对于传感器数据的获取,ART同样依赖与HAL的交互。以加速度传感器为例,应用通过ART提供的API请求传感器数据。
// art/runtime/jni/android_hardware_SensorManager_JNI.cc
extern "C" JNIEXPORT jfloatArray JNICALL
Java_android_hardware_SensorManager_getAccelerometerData(JNIEnv* env, jobject thiz) {
// 获取传感器服务实例
SensorService* sensor_service = GetSensorService();
if (sensor_service!= nullptr) {
// 通过传感器服务从HAL获取加速度传感器数据
float* data = sensor_service->GetAccelerometerData();
if (data!= nullptr) {
// 将数据转换为Java层可处理的格式
jfloatArray result = env->NewFloatArray(3);
env->SetFloatArrayRegion(result, 0, 3, data);
return result;
}
}
return nullptr;
}
Java_android_hardware_SensorManager_getAccelerometerData
函数展示了获取加速度传感器数据的过程。通过获取SensorService
实例,从HAL中读取传感器数据,并将其转换为Java层能够使用的jfloatArray
格式,实现应用对传感器数据的实时获取和处理。
17.3 音频硬件交互
在音频播放和录制方面,ART与HAL协同工作,确保音频数据的正确处理和传输。
// art/runtime/jni/android_media_AudioTrack_JNI.cc
extern "C" JNIEXPORT void JNICALL
Java_android_media_AudioTrack_nPlay(JNIEnv* env, jobject thiz) {
// 获取音频轨道实例
AudioTrack* audio_track = GetAudioTrackInstance(env, thiz);
if (audio_track!= nullptr) {
// 通过HAL音频设备将音频数据发送到硬件进行播放
audio_track->Play();
}
}
void AudioTrack::Play() {
// 打开HAL音频设备
AudioDevice* audio_device = OpenAudioDevice();
if (audio_device!= nullptr) {
// 将音频数据写入设备缓冲区
WriteAudioDataToDevice(audio_device, audio_data_);
// 启动音频播放
audio_device->Start();
}
}
Java_android_media_AudioTrack_nPlay
函数及相关代码展示了音频播放的交互逻辑。获取音频轨道实例后,通过与HAL音频设备的交互,将音频数据写入设备缓冲区并启动播放,实现高质量的音频输出。
十八、ART 内存管理的深度优化策略
ART的内存管理直接影响应用的性能和稳定性,其采用了多种深度优化策略来提升内存使用效率。
18.1 分代垃圾回收机制深化
ART的分代垃圾回收机制将对象分为不同代,根据对象存活时间的不同采用不同的回收策略。
// art/gc/heap.cc
void Heap::CollectGarbageInternal(GcCause gc_cause, bool clear_soft_references) {
// 优先回收年轻代
if (young_generation_->ShouldCollect(gc_cause)) {
young_generation_->Collect(gc_cause, clear_soft_references);
}
// 如果年轻代回收后内存仍不足,再回收老年代
if (GetFreeMemory() < required_memory && old_generation_->ShouldCollect(gc_cause)) {
old_generation_->Collect(gc_cause, clear_soft_references);
}
}
// art/gc/generation.cc
bool Generation::ShouldCollect(GcCause gc_cause) {
// 根据内存使用率和垃圾回收原因判断是否需要回收
if (GetMemoryUsage() > high_watermark_ || gc_cause == kGcCauseOutOfMemory) {
return true;
}
return false;
}
Heap::CollectGarbageInternal
函数展示了分代回收的执行流程。优先对年轻代进行回收,因为年轻代对象存活率低,回收成本相对较低;若年轻代回收后内存仍不足,再对老年代进行回收。Generation::ShouldCollect
函数通过内存使用率和垃圾回收原因判断是否触发回收操作,实现资源的合理利用。
18.2 大对象空间管理优化
对于大对象,ART将其分配到专门的大对象空间,并对该空间的管理进行优化。
// art/gc/space/large_object_space.cc
mirror::Object* LargeObjectSpace::AllocObject(Thread* self, mirror::Class* klass, size_t byte_count) {
// 检查大对象空间是否有足够内存
if (GetFreeMemory() < byte_count) {
// 触发大对象空间的垃圾回收
CollectGarbageForLargeObjects();
if (GetFreeMemory() < byte_count) {
return nullptr;
}
}
// 分配大对象
mirror::Object* obj = AllocateLargeObject(byte_count);
if (obj!= nullptr) {
InitializeObject(obj, klass);
}
return obj;
}
void LargeObjectSpace::CollectGarbageForLargeObjects() {
// 标记大对象空间中的存活对象
MarkLiveObjects();
// 压缩大对象空间,整理内存碎片
CompactSpace();
}
LargeObjectSpace::AllocObject
函数在分配大对象时,先检查空间内存是否充足,不足则触发垃圾回收。CollectGarbageForLargeObjects
函数通过标记存活对象和压缩空间,减少内存碎片,提高大对象空间的内存利用率。
18.3 内存预分配与缓存策略
ART采用内存预分配和缓存策略,减少频繁分配和释放内存带来的开销。
// art/gc/allocator/thread_local_allocator.cc
void ThreadLocalAllocator::Initialize() {
// 预分配一定大小的内存块
preallocated_memory_ = AllocatePreallocatedMemory(preallocation_size_);
if (preallocated_memory_!= nullptr) {
// 创建内存缓存池
memory_cache_ = CreateMemoryCache(preallocated_memory_, preallocation_size_);
}
}
void* ThreadLocalAllocator::Alloc(size_t byte_count) {
// 优先从内存缓存池中分配内存
void* result = AllocateFromCache(byte_count);
if (result == nullptr) {
// 缓存不足时,从预分配内存中分配
result = AllocateFromPreallocatedMemory(byte_count);
if (result == nullptr) {
// 预分配内存不足,请求系统分配新内存
result = AllocateFromSystem(byte_count);
}
}
return result;
}
ThreadLocalAllocator::Initialize
函数在初始化时预分配内存并创建缓存池。ThreadLocalAllocator::Alloc
函数在分配内存时,优先从缓存池中获取,不足则依次从预分配内存和系统分配内存,减少内存分配的系统调用开销,提升内存分配效率。
十九、ART 多进程通信(IPC)的底层实现
在Android系统中,多进程通信是应用间交互和系统服务调用的基础,ART在IPC的底层实现上提供了重要支持。
19.1 Binder 机制的集成
Binder是Android中最主要的IPC机制,ART深度集成Binder,实现进程间的高效通信。
// art/runtime/binder.cc
class BinderTransaction {
public:
BinderTransaction() {
// 初始化Binder事务相关数据结构
data_ = nullptr;
reply_ = nullptr;
target_handle_ = 0;
}
// 发起Binder事务
status_t Transact(int32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
// 将数据打包到Parcel中
data_.WriteFromParcel(data);
// 通过Binder驱动发送事务请求
status_t result = IPCThreadState::self()->transact(target_handle_, code, data_, reply, flags);
if (result == NO_ERROR && reply!= nullptr) {
// 处理事务回复
reply_->ReadFromParcel(*reply);
}
return result;
}
private:
Parcel data_;
Parcel reply_;
int32_t target_handle_;
};
class IPCThreadState : public RefBase {
public:
static IPCThreadState* self() {
if (gSelf == nullptr) {
gSelf = new IPCThreadState();
}
return gSelf;
}
status_t transact(int32_t handle, int32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
// 构建Binder事务数据
binder_transaction_data tr;
tr.target.handle = handle;
tr.code = code;
tr.flags = flags;
tr.data_size = data.dataSize();
tr.offsets_size = data.dataPosition();
tr.data.ptr.buffer = data.data();
tr.data.ptr.offsets = data.dataPosition();
// 通过ioctl系统调用与Binder驱动交互
return ioctl(binder_fd_, BINDER_WRITE_READ, &tr);
}
private:
static IPCThreadState* gSelf;
int binder_fd_;
};
BinderTransaction::Transact
函数发起Binder事务,将数据打包后通过IPCThreadState::transact
函数与Binder驱动进行交互。IPCThreadState::transact
函数构建Binder事务数据,并通过ioctl
系统调用将数据发送给Binder驱动,实现进程间的数据传递和方法调用。
19.2 Socket 通信的支持
除了Binder,ART也支持通过Socket进行进程间通信,适用于一些对性能和灵活性要求较高的场景。
// art/runtime/socket_ipc.cc
int SocketIpc::CreateSocket() {
// 创建Socket文件描述符
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0) {
LOG(ERROR) << "Failed to create socket";
return -1;
}
return socket_fd;
}
bool SocketIpc::Connect(const char* ip_address, int port) {
int socket_fd = CreateSocket();
if (socket_fd < 0) {
return false;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
inet_pton(AF_INET,
二十、ART 中的异常处理与错误恢复机制
在应用程序运行过程中,异常情况难以避免,ART 构建了一套完善的异常处理与错误恢复机制,确保系统的稳定性和应用的正常运行。
20.1 异常类型定义与分类
ART 在源码中定义了丰富的异常类型,这些类型继承自 Java 标准的异常体系,并根据 Android 运行时的特点进行了扩展。相关代码主要分布在 art/runtime/exceptions.h
和 art/runtime/exceptions.cc
文件中。
// art/runtime/exceptions.h
namespace art {
// 基础异常类,继承自 std::exception
class Exception : public std::exception {
public:
// 获取异常信息
const char* what() const noexcept override;
// 设置异常信息
void SetMessage(const char* message);
private:
std::string message_;
};
// Java 层的 OutOfMemoryError 异常类
class OutOfMemoryError : public Exception {
public:
OutOfMemoryError() { SetMessage("OutOfMemoryError"); }
};
// Java 层的 NullPointerException 异常类
class NullPointerException : public Exception {
public:
NullPointerException() { SetMessage("NullPointerException"); }
};
// 其他如 IllegalArgumentException、ArrayIndexOutOfBoundsException 等异常类定义类似
}
通过定义这些异常类,ART 能够清晰地区分不同类型的异常,为后续的异常处理提供准确的依据。在运行时,当出现内存不足、空指针引用等情况时,会实例化对应的异常类对象,传递异常信息。
20.2 异常抛出与捕获流程
当 ART 检测到异常情况时,会按照特定流程抛出异常,并由相应的代码块进行捕获处理。
// art/runtime/interpreter/interpreter.cc
JValue Execute(Thread* self, const DexFile::CodeItem* code_item,
ShadowFrame* shadow_frame, JValue result_register,
bool trace, bool log_interpreter_usage) {
// 获取字节码数组和方法信息
const uint16_t* insns = code_item->insns_;
uint32_t dex_pc = 0;
// 解释执行循环
while (true) {
// 获取当前指令
uint16_t opcode = insns[dex_pc] & 0xff;
// 根据操作码执行相应操作
switch (opcode) {
case Instruction::NOP:
dex_pc += 1;
break;
case Instruction::NEW_INSTANCE: {
// 创建新对象
mirror::Class* clazz = DecodeClassType(insns[dex_pc + 1]);
if (clazz == nullptr) {
// 类加载失败,抛出 ClassNotFoundException
ThrowClassNotFoundException(self, "Class not found");
return JValue();
}
mirror::Object* obj = self->GetHeap()->AllocObject(self, clazz, clazz->GetInstanceSize());
if (obj == nullptr) {
// 内存分配失败,抛出 OutOfMemoryError
ThrowOutOfMemoryError(self, "Failed to allocate object");
return JValue();
}
// 将对象引用压入操作数栈
PushReference(self, shadow_frame, obj);
dex_pc += 2;
break;
}
// 其他指令处理...
default:
LOG(FATAL) << "Unsupported opcode: " << opcode;
return JValue();
}
// 检查线程是否被中断
if (UNLIKELY(self->IsExceptionPending())) {
// 处理异常
return HandleException(self, shadow_frame);
}
}
}
JValue HandleException(Thread* self, ShadowFrame* shadow_frame) {
// 获取当前异常
Exception* exception = self->GetException();
// 查找异常处理代码块
for (const auto& handler : shadow_frame->GetExceptionHandlers()) {
if (handler.IsHandlerFor(exception)) {
// 跳转到异常处理代码块
return JumpToExceptionHandler(self, shadow_frame, handler);
}
}
// 未找到异常处理代码块,向上层抛出异常
return PropagateException(self, shadow_frame);
}
在字节码解释执行过程中,如 Execute
函数所示,当遇到指令执行错误或特殊情况(如类加载失败、内存分配失败)时,会调用相应的函数抛出异常。HandleException
函数负责处理异常,首先查找当前栈帧中的异常处理代码块,如果找到则跳转到对应代码块执行;若未找到,则将异常向上层传播,直至被捕获或导致应用崩溃。
20.3 错误恢复策略
对于一些可恢复的错误,ART 制定了相应的恢复策略,以减少异常对应用运行的影响。
// art/runtime/heap.cc
void Heap::HandleAllocationFailure(Thread* self, size_t num_bytes) {
// 记录分配失败
allocation_failures_count_++;
// 尝试触发垃圾回收,释放内存
if (allocation_failures_count_ % gc_trigger_frequency_ == 0) {
CollectGarbageInternal(kGcCauseAlloc, false);
}
// 检查是否有大对象空间可以分配
if (num_bytes > kMaxSmallObjectSize && large_object_space_->GetFreeMemory() >= num_bytes) {
// 从大对象空间分配内存
mirror::Object* obj = large_object_space_->AllocObject(self, nullptr, num_bytes);
if (obj!= nullptr) {
return;
}
}
// 内存仍然不足,抛出 OutOfMemoryError 异常
ThrowOutOfMemoryError(self, "Failed to allocate memory after GC", num_bytes);
}
在内存分配失败时,Heap::HandleAllocationFailure
函数首先记录失败次数,达到一定频率后触发垃圾回收,尝试释放内存。若垃圾回收后仍无法满足分配需求,且对象为大对象,则尝试从大对象空间分配。只有在所有尝试均失败的情况下,才抛出 OutOfMemoryError
异常,尽可能保证应用在内存紧张情况下的继续运行。
二十一、ART 源码中的资源管理与优化
ART 不仅负责应用程序的代码执行,还承担着资源管理的重要任务,通过合理的资源管理与优化策略,提升系统资源利用率和应用性能。
21.1 代码资源管理
ART 对应用程序的代码资源(如字节码、编译后的机器码)进行有效管理。在 AOT 编译过程中,生成的 OAT 文件存储着编译后的机器码,ART 会对 OAT 文件进行组织和维护。
// art/oat/oat_file.cc
class OatFile {
public:
// 打开 OAT 文件
static std::unique_ptr<OatFile> Open(const std::string& oat_file_path) {
std::ifstream file(oat_file_path, std::ios::binary);
if (!file.is_open()) {
return nullptr;
}
std::unique_ptr<OatFile> oat_file(new OatFile());
if (!oat_file->ReadHeader(file)) {
return nullptr;
}
if (!oat_file->ReadSections(file)) {
return nullptr;
}
return oat_file;
}
// 读取 OAT 文件头
bool ReadHeader(std::ifstream& file) {
file.read(reinterpret_cast<char*>(&header_), sizeof(header_));
if (file.gcount()!= sizeof(header_)) {
return false;
}
return true;
}
// 读取 OAT 文件各个节
bool ReadSections(std::ifstream& file) {
for (size_t i = 0; i < header_.num_sections_; ++i) {
OatSectionHeader section_header;
file.read(reinterpret_cast<char*>(§ion_header), sizeof(section_header));
if (file.gcount()!= sizeof(section_header)) {
return false;
}
std::unique_ptr<OatSection> section = CreateOatSection(section_header);
if (!section->ReadData(file)) {
return false;
}
sections_.push_back(std::move(section));
}
return true;
}
// 获取 OAT 文件中的代码段
const uint8_t* GetCodeSection() const {
for (const auto& section : sections_) {
if (section->GetType() == kOatSectionTypeCode) {
return section->GetData();
}
}
return nullptr;
}
private:
OatFileHeader header_;
std::vector<std::unique_ptr<OatSection>> sections_;
};
OatFile
类提供了打开、读取 OAT 文件的功能,通过读取文件头和各个节,将 OAT 文件的内容加载到内存中。GetCodeSection
函数可获取 OAT 文件中的代码段,方便 ART 在运行时执行编译后的机器码,实现对代码资源的高效管理和利用。
21.2 内存资源优化管理
除了垃圾回收机制,ART 还采用其他策略优化内存资源使用。例如,对内存页的管理和复用。
// art/gc/space/memory_page_manager.cc
class MemoryPageManager {
public:
MemoryPageManager() {
// 初始化内存页池
free_pages_.clear();
used_pages_.clear();
}
// 分配内存页
MemoryPage* AllocatePage() {
if (free_pages_.empty()) {
// 内存页池为空,向系统申请新的内存页
MemoryPage* new_page = AllocateNewPageFromSystem();
if (new_page!= nullptr) {
return new_page;
}
return nullptr;
}
// 从内存页池中获取空闲页
MemoryPage* page = free_pages_.back();
free_pages_.pop_back();
used_pages_.push_back(page);
return page;
}
// 释放内存页
void FreePage(MemoryPage* page) {
auto it = std::find(used_pages_.begin(), used_pages_.end(), page);
if (it!= used_pages_.end()) {
used_pages_.erase(it);
free_pages_.push_back(page);
}
}
private:
// 空闲内存页列表
std::vector<MemoryPage*> free_pages_;
// 已使用内存页列表
std::vector<MemoryPage*> used_pages_;
// 向系统申请新的内存页
MemoryPage* AllocateNewPageFromSystem() {
// 调用系统内存分配函数
void* ptr = malloc(kPageSize);
if (ptr == nullptr) {
return nullptr;
}
return new MemoryPage(ptr);
}
};
MemoryPageManager
类维护着内存页池,通过 AllocatePage
函数分配内存页,优先从空闲页列表中获取,若为空则向系统申请新页;FreePage
函数用于释放内存页,将其归还到空闲页列表,实现内存页的复用,减少内存碎片,提高内存资源的利用效率。
21.3 系统资源访问控制
ART 对应用程序访问系统资源(如文件系统、网络等)进行严格控制,确保资源的合理使用和安全性。
// art/runtime/security_manager.cc
class SecurityManager {
public:
// 检查文件读取权限
bool CheckFileReadPermission(const char* file_path) {
// 获取当前应用的权限列表
const std::vector<std::string>& permissions = GetAppPermissions();
for (const auto& permission : permissions) {
if (permission == "android.permission.READ_EXTERNAL_STORAGE" && DoesFileExistInExternalStorage(file_path)) {
return true;
}
}
return false;
}
// 检查网络访问权限
bool CheckNetworkAccessPermission() {
const std::vector<std::string>& permissions = GetAppPermissions();
for (const auto& permission : permissions) {
if (permission == "android.permission.INTERNET") {
return true;
}
}
return false;
}
private:
// 获取应用权限列表的实现
std::vector<std::string> GetAppPermissions();
// 判断文件是否在外部存储的实现
bool DoesFileExistInExternalStorage(const char* file_path);
};
SecurityManager
类通过 CheckFileReadPermission
和 CheckNetworkAccessPermission
等函数,检查应用是否具备相应的系统资源访问权限。在应用尝试访问文件或网络时,ART 调用这些函数进行权限验证,只有权限通过的情况下才允许访问,保障系统资源的安全和稳定。
二十二、ART 与 Android 系统启动流程的深度融合
Android 系统的启动过程中,ART 的初始化和加载是关键环节,它与系统启动流程深度融合,为应用程序的运行做好准备。
22.1 系统启动初期的 ART 初始化
在 Android 系统启动初期,Zygote 进程的启动涉及 ART 的初始化操作。相关代码主要在 art/runtime/zygote.cc
文件中。
// art/runtime/zygote.cc
void ZygoteInit() {
// 创建 ART 运行时实例
Runtime* runtime = Runtime::Create();
if (runtime == nullptr) {
LOG(ERROR) << "Failed to create ART runtime in Zygote";
return;
}
// 设置运行时参数
runtime->SetParameter("jit.profile引导类加载器提前编译", "true");
runtime->SetParameter("heapgrowthlimit", "512m");
// 预加载核心类和资源
PreloadClasses();
PreloadResources();
// 启动 Zygote 服务器,等待应用进程创建请求
StartZygoteServer();
}
void PreloadClasses() {
// 打开预加载类列表文件
std::ifstream preload_classes_file("/system/etc/preloaded-classes");
if (!preload_classes_file.is_open()) {
LOG(ERROR) << "Failed to open preloaded-classes file";
return;
}
std::string class_name;
while (std::getline(preload_classes_file, class_name)) {
// 加载类
mirror::Class* clazz = ClassLinker::Get().FindClass(nullptr, class_name.c_str());
if (clazz!= nullptr) {
// 解析类的成员,完成预加载
ClassLinker::Get().LinkClass(clazz);
}
}
}
ZygoteInit
函数负责初始化 ART 运行时,创建 Runtime
实例并设置相关参数,如 JIT 编译选项和堆内存增长限制。通过 PreloadClasses
函数预加载核心类,从预加载类列表文件中读取类名,加载并链接这些类,减少后续应用进程启动时的类加载时间,提升系统启动速度和应用启动效率。
22.2 应用进程启动时的 ART 准备
当 Zygote 进程fork出新的应用进程后,ART 需要为应用进程进行一系列准备工作。
// art/runtime/application.cc
void Application::Initialize() {
// 获取当前线程
Thread* self = Thread::Current();
// 创建应用的类加载器
ClassLoader* class_loader = CreateClassLoader();
// 设置应用的上下文
SetApplicationContext(CreateApplicationContext());
// 加载应用的主类
mirror::Class* main_class = class_loader->FindClass(nullptr, "com.example.MyApplication");
if (main_class!= nullptr) {
// 调用应用主类的 onCreate 方法
ArtMethod* onCreateMethod = main_class->GetMethodByName("onCreate", "()V");
if (onCreateMethod!= nullptr) {
JValue result;
onCreateMethod->Invoke(self, &result, nullptr);
}
}
}
ClassLoader* Application::CreateClassLoader() {
// 创建路径类加载器,加载应用的 DEX 文件
PathClassLoader* class_loader = new PathClassLoader("/data/app/com.example.myapp-1/base.apk", nullptr);
return class_loader;
}
Application::Initialize
函数在应用进程启动时执行,创建类加载器用于加载应用的代码,设置应用上下文,并找到应用的主类,调用其 onCreate
方法。CreateClassLoader
函数创建 PathClassLoader
,指定应用的 APK 文件路径,实现应用代码的加载,使 ART 能够为应用提供完整的运行环境。