一、ART源码工程整体架构概览
1.1 ART在AOSP中的位置
Android Runtime(ART)源码位于Android Open Source Project(AOSP)的art目录下,是整个Android系统的核心执行环境。它向上对接应用框架层(如Activity、Service等组件),向下依赖Linux内核提供的基础服务,承担着Java字节码执行、内存管理、类加载等关键任务。在AOSP的代码树中,art目录与frameworks(应用框架)、kernel(内核相关)等目录共同构成了Android系统的底层支撑体系。
1.2 工程结构设计目标
ART源码工程结构的设计旨在实现高内聚、低耦合,便于开发者进行代码维护、功能扩展和性能优化。其核心目标包括:
- 模块化管理:将不同功能划分为独立模块,如运行时、编译器、工具等,提高代码的可维护性
- 平台适配性:支持ARM、x86等多种硬件架构,通过架构相关代码分离实现
- 扩展性:为新特性开发和技术演进预留接口,如混合编译模式的引入
- 性能优化:通过合理的代码组织,便于进行编译优化和运行时性能调优
1.3 核心目录结构总览
art目录下包含多个核心子目录,每个子目录负责特定功能:
runtime:ART运行时核心代码,涵盖内存管理、线程调度、垃圾回收等compiler:AOT编译器、JIT编译器及中间表示(IR)优化相关代码dex:处理DEX文件格式解析、验证及优化libcore:Java核心库的本地实现tools:编译工具、调试工具及性能分析工具include:存放公共头文件,用于模块间接口定义test:包含单元测试、集成测试等各类测试代码
二、runtime目录:ART运行时核心实现
2.1 内存管理子模块
内存管理相关代码位于runtime/gc目录,核心类为Heap,定义于runtime/gc/heap.cc:
// runtime/gc/heap.cc
class Heap {
public:
// 初始化堆内存,根据配置分配年轻代、老年代和大对象空间
void Initialize(Runtime* runtime);
// 执行垃圾回收操作
void CollectGarbage(GcType gc_type, GcCause gc_cause);
// 分配对象内存
mirror::Object* AllocObject(Class* clazz, size_t extra_bytes);
private:
// 年轻代对象分配器
GcAllocator* young_allocator_;
// 老年代对象分配器
GcAllocator* old_allocator_;
// 大对象空间
LargeObjectSpace* large_object_space_;
};
Heap类通过分代式内存管理策略,将堆内存划分为年轻代、老年代和大对象空间,不同代采用不同的垃圾回收算法:
- 年轻代:使用复制算法,在
runtime/gc/collector/scavenge.cc实现 - 老年代:采用标记-压缩算法,在
runtime/gc/collector/marksweep.cc实现
2.2 线程管理模块
线程相关代码集中在runtime/thread.cc和runtime/thread_list.cc:
// runtime/thread.cc
class Thread : public StackHandle<mirror::Object> {
public:
// 线程初始化,设置线程ID、栈空间等
static Thread* CreateNativeThread(ThreadStartRunnable* runnable, size_t stack_size);
// 线程入口函数,执行Java方法
void Run();
// 获取当前线程的JNIEnv指针
JNIEnv* GetJniEnv();
private:
// 线程状态(运行、阻塞、等待等)
ThreadState state_;
// 线程本地存储(TLS)
void* tls_;
// 调用栈信息
StackHandle<mirror::ObjectArray<mirror::Object>> stack_;
};
Thread类负责管理线程生命周期,通过pthread库与Linux内核线程进行交互,并实现Java线程与Native线程的映射关系。ThreadList类则用于维护系统中所有线程的列表,支持线程的创建、销毁和状态查询。
2.3 类加载与链接模块
类加载核心逻辑在runtime/class_linker.cc实现:
// runtime/class_linker.cc
class ClassLinker {
public:
// 加载类,包括验证、准备和解析阶段
std::unique_ptr<mirror::Class> LoadClass(ClassLoader* class_loader, const DexFile& dex_file, uint32_t class_def_idx);
// 链接类,解析类的静态字段和方法
void LinkClass(mirror::Class* clazz);
// 初始化类,执行类的静态初始化块
void InitializeClass(mirror::Class* clazz);
private:
// 类加载器注册表
ClassLoaderRegistry class_loader_registry_;
// 已加载类的缓存
ClassTable class_table_;
};
ClassLinker类遵循Java类加载机制,实现双亲委托模型,并对DEX文件中的类进行验证、链接和初始化。同时,通过缓存机制优化类查找效率,减少重复加载开销。
三、compiler目录:编译系统核心实现
3.1 AOT编译器架构
AOT编译由dex2oat工具驱动,核心代码位于compiler/dex2oat目录。Dex2Oat类在compiler/dex2oat/dex2oat.cc中定义:
// compiler/dex2oat/dex2oat.cc
class Dex2Oat {
public:
// 解析命令行参数,配置编译选项
bool ParseCommandLine(int argc, char** argv);
// 执行AOT编译流程
int Run();
private:
// DEX文件解析器
std::unique_ptr<DexFile> dex_file_;
// 中间表示(HGraph)生成器
HGraphBuilder hgraph_builder_;
// 机器码生成器
MachineCodeGenerator machine_code_generator_;
// 输出的OAT文件路径
std::string output_oat_file_;
};
AOT编译流程包括:
- DEX文件解析:验证文件格式并提取字节码
- 中间表示生成:构建HGraph(控制流图和数据流图)
- 优化阶段:进行常量折叠、死代码消除等优化
- 机器码生成:针对目标架构生成二进制指令
- 输出OAT文件:包含机器码和元数据
3.2 JIT编译器实现
JIT编译器代码位于compiler/jit目录,JitCompiler类在compiler/jit/jit_compiler.cc中定义:
// compiler/jit/jit_compiler.cc
class JitCompiler {
public:
// 编译热点方法
void CompileMethod(Method* method);
// 生成中间表示(IR)
IRGenerator* GenerateIR(Method* method);
// 优化IR代码
void OptimizeIR(IRGenerator* ir_generator);
// 生成机器码
void GenerateMachineCode(IRGenerator* ir_generator);
private:
// 热点方法探测表
MethodCounterTable method_counter_table_;
// 编译队列,管理待编译方法
CompilationQueue compilation_queue_;
};
JIT编译器通过热点探测机制识别高频调用方法,动态生成机器码替换解释执行路径。其优化过程包括局部优化(如寄存器分配)和全局优化(如函数内联)。
3.3 中间表示(IR)优化
IR优化核心在compiler/optimizing目录实现,以HGraphOptimizer类为例(compiler/optimizing/h_graph_optimizer.cc):
// compiler/optimizing/h_graph_optimizer.cc
class HGraphOptimizer {
public:
// 执行多阶段优化
void Optimize(HGraph* hgraph);
private:
// 常量传播优化
void PerformConstantPropagation(HGraph* hgraph);
// 死代码消除
void EliminateDeadCode(HGraph* hgraph);
// 函数内联优化
void InlineFunctions(HGraph* hgraph);
};
通过对HGraph的分析和转换,实现全局常量传播、死代码消除、循环优化等操作,提升代码执行效率。
四、dex目录:DEX文件处理核心
4.1 DEX文件格式解析
DexFile类在dex/DexFile.cpp中实现DEX文件解析:
// dex/DexFile.cpp
class DexFile {
public:
// 打开DEX文件并解析
static std::unique_ptr<DexFile> Open(const std::string& location);
// 获取DEX文件中的类定义数量
size_t NumClassDefs() const;
// 根据索引获取类定义
const DexFile::ClassDef& GetClassDef(uint32_t index) const;
// 获取方法定义
const DexFile::Method* GetMethod(uint32_t index) const;
private:
// 文件头信息
const DexFileHeader* header_;
// 字符串索引表
const StringId* string_ids_;
// 类型索引表
const TypeId* type_ids_;
// 类定义表
const ClassDef* class_defs_;
};
DexFile类解析DEX文件的各个部分,包括文件头、字符串表、类型表、类定义表等,并提供接口获取文件内的元数据和字节码信息。
4.2 DEX验证机制
DEX验证逻辑在dex/verifier目录实现,DexVerifier类负责验证字节码合法性(dex/verifier/dex_verifier.cc):
// dex/verifier/dex_verifier.cc
class DexVerifier {
public:
// 验证DEX文件中的所有方法
bool Verify(const DexFile& dex_file);
private:
// 验证单个方法的字节码
bool VerifyMethod(const DexFile::Method& method);
// 检查操作数栈和寄存器使用合法性
bool CheckStackAndRegisters(const DexFile::CodeItem& code_item);
// 验证指令操作数类型匹配
bool VerifyInstruction(const Instruction& insn);
};
验证过程包括:
- 检查文件格式完整性
- 验证类、方法和字段定义
- 分析字节码指令合法性
- 确保操作数栈和寄存器使用正确
4.3 DEX优化处理
dex/opt目录实现DEX优化功能,DexOptimizer类负责优化DEX文件(dex/opt/dex_optimizer.cc):
// dex/opt/dex_optimizer.cc
class DexOptimizer {
public:
// 对DEX文件进行优化
void Optimize(DexFile* dex_file);
private:
// 重写类定义,合并重复信息
void RewriteClassDefs(DexFile* dex_file);
// 优化方法调用指令
void OptimizeMethodCalls(DexFile* dex_file);
// 压缩字符串表和类型表
void CompressTables(DexFile* dex_file);
};
优化操作包括:
- 消除冗余类和方法定义
- 优化方法调用指令编码
- 压缩索引表减少文件大小
- 调整字节码顺序提升执行效率
五、libcore目录:Java核心库本地实现
5.1 基础类库实现
Java核心类库如java.lang、java.util的本地实现位于libcore目录。以String类为例,其本地方法在libcore/libart/src/main/java/java/lang/String.java中声明,并在runtime/native/java_lang_String.cc实现:
// runtime/native/java_lang_String.cc
extern "C" JNIEXPORT jstring JNICALL
Java_java_lang_String_utf8ToString(JNIEnv* env, jclass clazz, jbyteArray byte_array) {
// 获取字节数组长度
jsize length = env->GetArrayLength(byte_array);
// 分配Java字符串对象
jstring result = env->NewStringUtf((const char*)env->GetByteArrayElements(byte_array, nullptr));
// 释放字节数组资源
env->ReleaseByteArrayElements(byte_array, nullptr, 0);
return result;
}
通过JNI(Java Native Interface)实现Java方法与本地代码的交互,提供字符串编码转换、内存分配等功能。
5.2 集合框架实现
java.util包中的集合框架在libcore/libart/src/main/java/java/util目录实现。以ArrayList为例,其核心操作在libcore/libart/src/main/java/java/util/ArrayList.java定义:
// libcore/libart/src/main/java/java/util/ArrayList.java
public class ArrayList<E> extends AbstractList<E> implements RandomAccess, Cloneable, java.io.Serializable {
transient Object[] elementData; // 存储元素的数组
private int size; // 当前元素数量
public ArrayList() {
elementData = EMPTY_ELEMENTDATA;
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保数组容量足够
elementData[size++] = e;
return true;
}
// 其他方法...
}
通过数组实现动态扩容,结合System.arraycopy等本地方法实现高效的数据操作。
5.3 I/O与网络库实现
java.io和java.net包的本地实现分布在libcore/io和libcore/net目录。以Socket类为例,其网络操作通过JNI调用系统Socket API实现:
// libcore/luni/src/main/native/libcore_io_Socket.cpp
static jint listen_native(JNIEnv* env, jobject java_socket, jint backlog) {
// 获取Socket文件描述符
int fd = getFd(env, java_socket);
// 调用系统listen函数
int result = listen(fd, backlog);
if (result == -1) {
// 处理错误,设置Java异常
throwErrnoException(env, "listen failed");
}
return result;
}
通过封装Linux网络API,提供Java层面的网络通信接口。
六、tools目录:开发工具链实现
6.1 编译工具
dex2oat工具在tools/dex2oat目录实现,前文已详述其AOT编译流程。此外,aapt(Android Asset Packaging Tool)工具在tools/aapt目录,负责打包应用资源文件:
// tools/aapt/aapt_main.cc
int main(int argc, char** argv) {
// 解析命令行参数
CommandLineOptions options;
if (!options.Parse(argc, argv)) {
return -1;
}
// 创建资源打包器
ResourcePackageBuilder builder(options.output_package_file);
// 添加资源文件(XML、图片等)
builder.AddFiles(options.input_files);
// 生成APK中的资源索引表
builder.Build();
return 0;
}
aapt工具将资源文件编译为二进制格式,并生成资源ID映射表,供应用运行时使用。
6.2 调试工具
调试工具相关代码在tools/debugger目录,jdwp(Java Debug Wire Protocol)实现位于runtime/jdwp。JdwpThread类负责处理调试命令(runtime/jdwp/jdwp_thread.cc):
// runtime/jdwp/jdwp_thread.cc
class JdwpThread : public Thread {
public:
// 处理调试命令
void HandleCommand();
// 发送调试响应
void SendResponse(JdwpPacket* packet);
// 接收调试命令
bool ReceiveCommand(JdwpPacket* packet);
private:
// JDWP连接套接字
int socket_fd_;
// 命令解析器
JdwpCommandParser parser_;
};
通过监听调试端口,接收并处理来自调试器的命令(如断点设置、变量查询),实现Java程序的远程调试功能。
6.3 性能分析工具
Perfetto相关工具在tools/perfetto目录,用于收集和分析系统性能数据。PerfettoTraceBuffer类负责数据缓冲区管理(tools/perfetto/perfetto_trace_buffer.cc):
// tools/perfetto/perfetto_trace_buffer.cc
class PerfettoTraceBuffer {
public:
// 初始化缓冲区
void Initialize(size_t buffer_size);
// 写入性能数据
void WriteTraceData(const void* data, size_t size);
// 刷新缓冲区到磁盘
void Flush();
private:
// 环形缓冲区
char* buffer_;
// 缓冲区大小
size_t buffer_size_;
// 当前写入位置
size_t write_index_;
};
通过高效的数据采集和存储机制,支持CPU占用、内存分配等性能指标的实时监控。
七、include目录:公共头文件管理
7.1 模块间接口定义
include目录作为ART源码工程中模块间通信的桥梁,存放着大量公共头文件,用于定义各模块对外暴露的接口。以runtime模块与compiler模块的交互为例,在include/art/runtime/class_linker.h中定义了ClassLinker类的声明:
// include/art/runtime/class_linker.h
#ifndef ART_RUNTIME_CLASS_LINKER_H_
#define ART_RUNTIME_CLASS_LINKER_H_
#include "art/runtime/base/callee_save_type.h"
#include "art/runtime/base/macros.h"
#include "art/runtime/class_loader.h"
#include "art/runtime/dex_file.h"
#include "art/runtime/mirror/class.h"
#include "art/runtime/native_method.h"
namespace art {
class ClassLinker {
public:
// 从DEX文件加载类,参数包括类加载器、DEX文件实例以及类定义索引
std::unique_ptr<mirror::Class> LoadClass(ClassLoader* class_loader, const DexFile& dex_file,
uint32_t class_def_idx);
// 链接指定的类,完成类的准备工作
void LinkClass(mirror::Class* clazz);
// 初始化类,执行类的静态初始化块
void InitializeClass(mirror::Class* clazz);
// 省略其他方法声明
private:
DISALLOW_COPY_AND_ASSIGN(ClassLinker);
ClassLoaderRegistry class_loader_registry_;
ClassTable class_table_;
};
} // namespace art
#endif // ART_RUNTIME_CLASS_LINKER_H_
compiler模块在进行AOT编译或JIT编译时,若涉及类加载相关操作,就会包含此头文件,调用ClassLinker类的方法。这种通过头文件暴露接口的方式,保证了模块间的低耦合,compiler模块无需了解runtime模块中ClassLinker类的具体实现细节,只需遵循头文件定义的接口规范即可进行交互。
7.2 数据结构与类型定义
该目录还承担着统一数据结构和类型定义的重要职责。例如,在include/art/base/types.h中定义了ART中常用的基础数据类型:
// include/art/base/types.h
#ifndef ART_BASE_TYPES_H_
#define ART_BASE_TYPES_H_
#include <stdint.h>
// 定义无符号8位整数类型
using uint8 = uint8_t;
// 定义有符号8位整数类型
using int8 = int8_t;
// 定义无符号16位整数类型
using uint16 = uint16_t;
// 定义有符号16位整数类型
using int16 = int16_t;
// 定义无符号32位整数类型
using uint32 = uint32_t;
// 定义有符号32位整数类型
using int32 = int32_t;
// 定义无符号64位整数类型
using uint64 = uint64_t;
// 定义有符号64位整数类型
using int64 = int64_t;
// 省略其他类型定义
#endif // ART_BASE_TYPES_H_
这些基础数据类型定义在整个ART源码工程中被广泛使用,确保了不同模块在数据类型表示上的一致性。当某个模块需要处理特定长度的整数数据时,直接使用include/art/base/types.h中定义的类型,避免了因数据类型定义不一致导致的错误,同时也方便了代码在不同平台和架构间的移植。
7.3 宏定义与常量声明
include目录中的头文件还包含大量宏定义和常量声明,用于控制代码的编译行为和功能配置。在include/art/compiler/optimizing/optimizing_common.h中,定义了与编译优化相关的宏:
// include/art/compiler/optimizing/optimizing_common.h
#ifndef ART_COMPILER_OPTIMIZING_OPTIMIZING_COMMON_H_
#define ART_COMPILER_OPTIMIZING_OPTIMIZING_COMMON_H_
// 定义是否启用常量传播优化的宏
#ifdef ENABLE_CONSTANT_PROPAGATION
#define DO_CONSTANT_PROPAGATION() \
{ \
// 执行常量传播优化的具体代码逻辑 \
}
#else
#define DO_CONSTANT_PROPAGATION()
#endif
// 定义是否启用死代码消除优化的宏
#ifdef ENABLE_DEAD_CODE_ELIMINATION
#define DO_DEAD_CODE_ELIMINATION() \
{ \
// 执行死代码消除优化的具体代码逻辑 \
}
#else
#define DO_DEAD_CODE_ELIMINATION()
#endif
// 省略其他宏定义
#endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMMON_H_
通过这些宏定义,可以在编译时灵活控制是否启用特定的优化功能。开发人员可以根据不同的需求和场景,通过修改宏定义的值(如在编译配置文件中定义ENABLE_CONSTANT_PROPAGATION为1来启用常量传播优化),快速调整ART的编译优化策略,而无需修改大量的源代码,提高了代码的可配置性和扩展性。
八、test目录:测试体系构建
8.1 单元测试实现
test目录下的单元测试代码主要用于验证各个模块中函数和类的基本功能是否正确。以runtime模块中的Heap类为例,在test/runtime/gc/heap_test.cc中编写单元测试:
// test/runtime/gc/heap_test.cc
#include "art/runtime/gc/heap.h"
#include "gtest/gtest.h"
TEST(HeapTest, AllocObjectTest) {
// 创建一个模拟的运行时环境
Runtime* runtime = CreateMockRuntime();
// 初始化堆内存
Heap heap;
heap.Initialize(runtime);
// 模拟创建一个类
mirror::Class* clazz = CreateMockClass();
// 调用AllocObject方法分配对象
mirror::Object* object = heap.AllocObject(clazz, 0);
// 验证对象是否分配成功
EXPECT_NE(object, nullptr);
// 释放资源
DestroyMockClass(clazz);
DestroyMockRuntime(runtime);
}
上述代码使用Google Test框架,创建了一个针对Heap类AllocObject方法的单元测试。通过模拟运行时环境和类对象,调用AllocObject方法并验证返回结果,确保该方法在正常情况下能够正确分配对象内存。单元测试能够快速定位单个函数或类中的逻辑错误,是保证代码质量的基础环节。
8.2 集成测试设计
集成测试关注多个模块之间的协同工作是否正常。在test/compiler/dex2oat_integration_test.cc中,对dex2oat工具(涉及compiler模块和dex模块)进行集成测试:
// test/compiler/dex2oat_integration_test.cc
#include "art/compiler/dex2oat/dex2oat.h"
#include "art/dex/dex_file.h"
#include "gtest/gtest.h"
TEST(Dex2OatIntegrationTest, BasicCompilationTest) {
// 准备测试用的DEX文件路径
std::string dex_file_path = GetTestDexFilePath();
// 准备输出的OAT文件路径
std::string oat_file_path = GetOutputOatFilePath();
// 创建Dex2Oat实例并解析命令行参数
Dex2Oat dex2oat;
std::vector<std::string> args = {
"--dex-file=" + dex_file_path,
"--oat-file=" + oat_file_path
};
EXPECT_TRUE(dex2oat.ParseCommandLine(args.size(), args.data()));
// 执行AOT编译
int result = dex2oat.Run();
EXPECT_EQ(result, 0);
// 验证生成的OAT文件是否存在且格式正确
std::unique_ptr<DexFile> oat_dex_file = DexFile::Open(oat_file_path);
EXPECT_NE(oat_dex_file, nullptr);
}
此集成测试模拟了dex2oat工具的实际运行过程,从输入DEX文件到输出OAT文件,验证了compiler模块和dex模块在AOT编译流程中的协作是否正常。通过检查生成的OAT文件是否存在且能够正确解析,确保整个编译过程没有出现致命错误,保障了不同模块组合后的功能正确性。
8.3 压力测试与性能测试
压力测试和性能测试用于评估ART在高负载和长时间运行情况下的表现。在test/runtime/performance/thread_performance_test.cc中进行线程相关的性能测试:
// test/runtime/performance/thread_performance_test.cc
#include "art/runtime/thread.h"
#include "art/runtime/runtime.h"
#include "gtest/gtest.h"
#include "time.h"
TEST(ThreadPerformanceTest, MultipleThreadCreationTest) {
Runtime* runtime = Runtime::Current();
const int thread_count = 1000;
clock_t start_time = clock();
for (int i = 0; i < thread_count; ++i) {
// 创建大量线程
Thread* thread = Thread::CreateNativeThread(nullptr, 1024 * 1024);
EXPECT_NE(thread, nullptr);
thread->Start();
}
// 等待所有线程执行完毕
for (int i = 0; i < thread_count; ++i) {
Thread* thread = GetThreadByIndex(i);
thread->Join();
}
clock_t end_time = clock();
double execution_time = ((double) (end_time - start_time)) / CLOCKS_PER_SEC;
// 设定性能阈值,验证创建和执行大量线程的时间是否在可接受范围内
EXPECT_TRUE(execution_time < 10.0);
}
该测试通过创建大量线程并统计创建和执行的总时间,与设定的性能阈值进行比较,判断ART在线程管理方面的性能表现。压力测试和性能测试能够发现代码在极端情况下的性能瓶颈和潜在问题,为优化ART的运行效率提供依据。
九、build目录:编译配置与构建逻辑
9.1 编译脚本核心逻辑
build目录中存放着ART的编译配置文件和构建脚本,核心编译逻辑在build/core/main.mk中实现。该文件定义了ART编译的基本规则和依赖关系:
# build/core/main.mk
# 定义ART编译输出目录
ART_OUT_DIR := $(OUT_DIR)/target/product/$(TARGET_PRODUCT)/obj/STATIC_LIBRARIES/libart_intermediates
# 定义ART核心源文件列表
ART_SRC_FILES := \
$(wildcard $(ART_DIR)/runtime/*.cc) \
$(wildcard $(ART_DIR)/compiler/*.cc) \
$(wildcard $(ART_DIR)/dex/*.cc)
# 定义编译目标
$(ART_OUT_DIR)/libart.a: $(ART_SRC_FILES)
$(CC) $(CFLAGS) -c $^ -o $@
$(AR) rcs $@ $^
# 定义依赖关系,确保在编译ART之前先编译相关依赖库
$(ART_OUT_DIR)/libart.a: $(LIBCORE_LIBRARY) $(OTHER_DEPENDENCIES)
上述makefile代码首先指定了ART的编译输出目录,然后通过通配符收集各模块的源文件,定义了将源文件编译为静态库libart.a的规则。同时,明确了编译ART时对其他库(如libcore库)的依赖关系,保证了编译过程的正确性和完整性。
9.2 架构适配编译配置
为了支持ARM、x86等多种硬件架构,build目录中有针对不同架构的编译配置文件。以ARM架构为例,在build/target/arch/arm/config.mk中定义了ARM架构相关的编译参数:
# build/target/arch/arm/config.mk
# 定义ARM架构的编译器
TARGET_GCC := arm-linux-androideabi-gcc
# 定义ARM架构的汇编器
TARGET_AS := arm-linux-androideabi-as
# 定义ARM架构的链接器
TARGET_LD := arm-linux-androideabi-ld
# 定义ARM架构特有的编译选项
TARGET_CFLAGS += -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp
TARGET_ASFLAGS += -march=armv7-a
TARGET_LDFLAGS += -Wl,--fix-cortex-a8
这些配置文件根据不同架构的特性,设置了相应的编译器、汇编器、链接器以及特定的编译选项。在编译过程中,构建系统会根据目标架构自动加载对应的配置文件,确保生成的ART二进制文件能够在该架构的设备上正确运行,实现了ART对多架构的良好适配。
9.3 编译选项与功能开关
build目录还提供了丰富的编译选项和功能开关,用于定制ART的编译行为。在build/soong/android/config/known_config.mk中定义了一些常用的编译选项:
# build/soong/android/config/known_config.mk
# 定义是否启用AOT编译的开关
ifeq ($(ENABLE_AOT_COMPILATION), true)
ART_COMPILE_FLAGS += --enable-aot
else
ART_COMPILE_FLAGS += --disable-aot
endif
# 定义是否启用JIT编译的开关
ifeq ($(ENABLE_JIT_COMPILATION), true)
ART_COMPILE_FLAGS += --enable-jit
else
ART_COMPILE_FLAGS += --disable-jit
endif
# 定义是否启用调试信息的开关
ifeq ($(ENABLE_DEBUG_INFO), true)
ART_COMPILE_FLAGS += --debug-info
else
ART_COMPILE_FLAGS += --no-debug-info
endif
通过设置这些编译选项和功能开关(如在编译环境变量中设置ENABLE_AOT_COMPILATION=true来启用AOT编译),开发者可以根据具体需求选择编译出具有不同功能特性的ART版本。这使得ART能够在性能、调试便利性、存储空间占用等方面进行灵活调整,满足多样化的开发和使用场景。
十、external目录:外部依赖管理
10.1 第三方库集成
external目录用于管理ART所依赖的第三方库。例如,external/libcxx目录集成了C++标准库的实现,ART在编译和运行过程中,涉及C++相关功能时会依赖该库。external/libcxx中的代码经过适配和修改,以满足ART的特定需求:
// external/libcxx/include/string
#ifndef LIBCXX_STRING
#define LIBCXX_STRING
#include <stddef.h>
namespace std {
class string {
public:
string(const char* s);
size_t length() const;
// 省略其他方法声明
private:
char* data_;
size_t size_;
};
} // namespace std
#endif // LIBCXX_STRING
通过将第三方库集成到external目录,ART实现了对外部依赖的统一管理。在编译过程中,构建系统会自动处理这些第三方库的编译和链接,确保它们与ART的其他模块正确协同工作,同时也避免了与系统中其他库的冲突。
10.2 依赖库版本控制
对于集成到external目录的依赖库,ART通过版本控制确保其稳定性和兼容性。以external/zlib库为例,在external/zlib/Android.bp文件中指定了库的版本信息和编译规则:
# external/zlib/Android.bp
cc_library_static {
name: "libz",
srcs: [
"adler32.c",
"compress.c",
"crc32.c",
"deflate.c",
"gzclose.c",
"gzlib.c",
"gzread.c",
"gzwrite.c",
"infback.c",
"inffast.c",
"inflate.c",
"inftrees.c",
"trees.c",
"uncompr.c",
"zutil.c",
],
export_include_dirs: ["include"],
cflags: [
"-O3",
"-D_LARGEFILE64_SOURCE",
"-D_FILE_OFFSET_BITS=64",
],
strip: false,
}
通过明确指定依赖库的源文件和编译参数,保证了在不同编译环境和版本迭代中,zlib库能够以一致的方式进行编译和使用。同时,当需要更新依赖库版本时,可以在该文件中进行修改,并评估对ART整体功能的影响,实现对依赖库版本的有效控制。
10.3 依赖库定制与优化
ART还会根据自身需求对依赖库进行定制和优化。在external/libunwind库的使用中,为了更好地支持堆栈回溯功能,对其进行了针对性修改。在external/libunwind/src/libunwind-x86_64.c中添加了特定的代码逻辑:
// external/libunwind/src/libunwind-x86_64.c
_Unwind_Reason_Code
_x86_64_local_get_reg(_Unwind_Context* context, int regnum,
_Unwind_Word* valp)
{
// 获取当前线程的上下文信息
struct x86_64_context* x86_64
// external/libunwind/src/libunwind-x86_64.c
_Unwind_Reason_Code
_x86_64_local_get_reg(_Unwind_Context* context, int regnum,
_Unwind_Word* valp)
{
// 获取当前线程的上下文信息
struct x86_64_context* x86_64_ctx = (struct x86_64_context*)context;
// 根据寄存器编号获取对应的值
switch (regnum) {
case _UNW_X86_64_RIP:
*valp = x86_64_ctx->rip;
return _URC_NO_REASON;
case _UNW_X86_64_RSP:
*valp = x86_64_ctx->rsp;
return _URC_NO_REASON;
// 其他寄存器处理...
default:
// 调用原始libunwind的实现
return __libunwind_default_get_reg(context, regnum, valp);
}
}
// 为ART优化的堆栈展开函数
_Unwind_Reason_Code
art_custom_unwind(struct _Unwind_Context* context, void* arg)
{
// 获取ART特定的回调函数
ArtUnwindCallback callback = (ArtUnwindCallback)arg;
// 获取当前帧的信息
_Unwind_Word ip = _Unwind_GetIP(context);
_Unwind_Word sp = _Unwind_GetSP(context);
// 调用ART的堆栈处理回调
if (callback != nullptr) {
return callback(ip, sp, context);
}
return _URC_CONTINUE_UNWIND;
}
上述代码展示了对libunwind库的定制优化。通过实现art_custom_unwind函数,ART能够以更高效的方式进行堆栈回溯,这对于异常处理、性能分析等功能至关重要。这种定制不仅提升了ART的性能,还确保了与Android系统其他组件的兼容性。
10.4 依赖库构建系统集成
为了将外部依赖库无缝集成到ART的构建系统中,每个依赖库都包含特定的构建配置文件。以external/protobuf为例,其Android.bp文件定义了编译规则:
// external/protobuf/Android.bp
cc_library_shared {
name: "libprotobuf-lite",
defaults: ["protobuf_defaults"],
srcs: [
"src/google/protobuf/any_lite.cc",
"src/google/protobuf/extension_set.cc",
"src/google/protobuf/generated_message_util.cc",
"src/google/protobuf/io/coded_stream.cc",
"src/google/protobuf/io/zero_copy_stream.cc",
"src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
"src/google/protobuf/message_lite.cc",
"src/google/protobuf/repeated_field.cc",
"src/google/protobuf/wire_format_lite.cc",
],
shared_libs: ["liblog", "libm"],
export_include_dirs: ["src"],
strip: {
none: true,
},
}
该配置文件指定了protobuf-lite库的源文件、依赖库以及导出的头文件目录。通过这种方式,ART的构建系统能够正确编译和链接protobuf库,确保其在运行时可用。这种集成方式也使得依赖库的更新和维护变得更加简单。
十一、dalvikvm目录:兼容性支持层
11.1 Dalvik兼容性实现
为了兼容基于Dalvik虚拟机开发的应用,ART在dalvikvm目录中实现了Dalvik虚拟机的部分接口。dalvikvm/Interp.cpp文件提供了Dalvik字节码解释器的基本框架:
// dalvikvm/Interp.cpp
/**
* Dalvik字节码解释器的主循环
*/
void dvmInterpret(Thread* self, Method* method, JValue* pResult)
{
// 获取方法的字节码
const u2* insns = method->insns;
// 获取方法的寄存器数量
u4 regCount = method->registersSize;
// 初始化解释器状态
InterpState interpState;
interpState.thread = self;
interpState.insns = insns;
interpState.pc = 0;
interpState.registers = (u4*)calloc(regCount, sizeof(u4));
// 解释执行字节码
while (true) {
// 获取当前指令
u2 opcode = insns[interpState.pc] & 0xff;
// 根据操作码执行相应的指令处理函数
switch (opcode) {
case OP_MOVE:
dvmInterpretMove(&interpState);
break;
case OP_RETURN_VOID:
// 方法返回,清理资源
free(interpState.registers);
return;
case OP_INVOKE_VIRTUAL:
dvmInterpretInvokeVirtual(&interpState);
break;
// 其他指令处理...
default:
// 未知指令,抛出异常
dvmThrowRuntimeException("Unknown opcode: %02x", opcode);
free(interpState.registers);
return;
}
// 更新程序计数器
interpState.pc++;
}
}
这个解释器虽然不如ART的AOT编译高效,但它允许Dalvik字节码在ART上运行,为应用迁移提供了平滑过渡。这种兼容性层的设计是ART能够在短时间内被广泛接受的关键因素之一。
11.2 JIT桥接模块
dalvikvm/jit目录实现了Dalvik JIT与ART JIT之间的桥接功能。dalvikvm/jit/JitBridge.cpp文件中的代码负责将Dalvik JIT编译的代码转换为ART可执行的形式:
// dalvikvm/jit/JitBridge.cpp
/**
* 将Dalvik JIT编译的代码转换为ART可以执行的形式
*/
bool dvmJitBridgeCompileMethod(Thread* self, Method* method)
{
// 检查方法是否已经被ART编译
if (method->isCompiled()) {
return true;
}
// 获取Dalvik JIT编译的代码
void* dalvikCode = dvmJitGetCompiledCode(method);
if (dalvikCode == nullptr) {
// 如果Dalvik JIT未编译此方法,使用ART的JIT编译
return art::Jit::Get()->CompileMethod(method, self);
}
// 创建ART的编译单元
art::CompilationUnit* unit = art::CompilationUnit::Create(method);
// 分析Dalvik编译的代码,提取基本块和控制流信息
art::CodeInfo codeInfo = analyzeDalvikCompiledCode(dalvikCode);
// 为ART生成中间表示
art::HGraph* graph = generateHGraphFromDalvikCode(unit, codeInfo);
// 使用ART的优化器优化中间表示
art::OptimizingCompiler::Optimize(graph);
// 生成ART机器码
art::CodeGenerator* codeGen = art::CodeGenerator::Create(unit, graph);
codeGen->GenerateCode();
// 安装生成的代码
method->setEntryPointFromQuickCompiledCode(codeGen->GetEntryPoint());
return true;
}
这种桥接机制允许基于Dalvik JIT优化的应用在ART上继续受益于这些优化,同时逐步迁移到ART的AOT编译模式。
11.3 兼容性配置与开关
dalvikvm/Config.cpp文件实现了Dalvik兼容性相关的配置管理:
// dalvikvm/Config.cpp
/**
* Dalvik兼容性配置
*/
struct DalvikCompatibilityConfig {
bool enableDalvikInterpreter; // 是否启用Dalvik解释器
bool enableJitBridging; // 是否启用JIT桥接功能
bool forceDalvikModeForOldApps; // 对旧应用强制使用Dalvik模式
// 其他配置选项...
};
// 默认配置
static DalvikCompatibilityConfig gCompatibilityConfig = {
.enableDalvikInterpreter = true,
.enableJitBridging = true,
.forceDalvikModeForOldApps = true,
};
/**
* 加载Dalvik兼容性配置
*/
void dvmLoadCompatibilityConfig()
{
// 从系统属性读取配置
const char* enableInterpreterProp = property_get("dalvik.vm.enableinterpreter");
if (enableInterpreterProp != nullptr) {
gCompatibilityConfig.enableDalvikInterpreter =
(strcmp(enableInterpreterProp, "true") == 0);
}
const char* enableJitBridgeProp = property_get("dalvik.vm.enablejitbridge");
if (enableJitBridgeProp != nullptr) {
gCompatibilityConfig.enableJitBridging =
(strcmp(enableJitBridgeProp, "true") == 0);
}
// 其他配置项加载...
}
/**
* 检查应用是否需要Dalvik兼容性模式
*/
bool dvmNeedsDalvikCompatibility(ApplicationInfo* appInfo)
{
// 检查应用的目标SDK版本
if (appInfo->targetSdkVersion < 21) {
// 对于目标SDK低于21的应用,默认启用Dalvik兼容性
return gCompatibilityConfig.forceDalvikModeForOldApps;
}
// 检查应用是否特别声明需要Dalvik兼容性
if (appInfo->flags & APP_FLAG_NEEDS_DALVIK_COMPAT) {
return true;
}
return false;
}
这些配置选项允许系统管理员和开发者根据应用的特性和需求,灵活控制Dalvik兼容性层的行为,确保旧应用能够在ART上正常运行。
十二、tools目录:开发工具链
12.4 性能分析工具
tools/perfetto目录中的代码实现了与Perfetto性能分析系统的集成。PerfettoConsumer类负责接收和处理性能数据:
// tools/perfetto/perfetto_consumer.cc
class PerfettoConsumer {
public:
// 初始化Perfetto消费者
bool Initialize(const std::string& config_file);
// 开始收集性能数据
bool StartTracing();
// 停止收集并获取追踪结果
bool StopTracing(std::string* trace_data);
// 处理接收到的性能数据包
void ProcessTracePacket(const perfetto::protos::TracePacket& packet);
private:
// 与Perfetto服务的连接
std::unique_ptr<perfetto::TracingService::Client> service_client_;
// 追踪会话
std::unique_ptr<perfetto::TracingSession> session_;
// 存储收集的追踪数据
std::string trace_buffer_;
};
bool PerfettoConsumer::StartTracing() {
// 读取追踪配置
perfetto::TraceConfig config;
if (!ReadConfigFromFile(config_file_, &config)) {
LOG(ERROR) << "Failed to read Perfetto config";
return false;
}
// 创建追踪会话
session_ = service_client_->NewTrace();
// 设置数据处理器
session_->SetOnTraceDataCallback(
[this](const std::vector<perfetto::protos::TracePacket>& packets, bool has_more) {
for (const auto& packet : packets) {
ProcessTracePacket(packet);
}
});
// 开始追踪
return session_->Start(config);
}
void PerfettoConsumer::ProcessTracePacket(const perfetto::protos::TracePacket& packet) {
// 处理不同类型的追踪事件
if (packet.has_process_descriptor()) {
// 处理进程描述信息
const auto& process = packet.process_descriptor();
LOG(INFO) << "Process: " << process.pid() << " - " << process.cmdline();
} else if (packet.has_thread_descriptor()) {
// 处理线程描述信息
const auto& thread = packet.thread_descriptor();
LOG(INFO) << "Thread: " << thread.tid() << " in process " << thread.pid();
} else if (packet.has_counter()) {
// 处理计数器数据(如CPU使用率)
const auto& counter = packet.counter();
LOG(INFO) << "Counter " << counter.name() << " = " << counter.value();
}
// 将数据包添加到追踪缓冲区
packet.SerializeToString(&trace_buffer_);
}
通过与Perfetto的集成,ART能够提供详细的性能分析数据,帮助开发者识别性能瓶颈和优化机会。
12.5 调试工具
tools/hprof目录实现了堆内存分析工具,用于生成和解析内存堆转储文件。HprofGenerator类负责生成Hprof格式的堆转储:
// tools/hprof/hprof_generator.cc
class HprofGenerator {
public:
// 初始化堆转储生成器
explicit HprofGenerator(Heap* heap);
// 生成堆转储文件
bool Generate(const std::string& output_path);
private:
// 写入Hprof文件头
void WriteHeader(FILE* file);
// 写入堆转储开始标记
void WriteHeapDumpStart(FILE* file);
// 遍历并写入所有类
void WriteClasses(FILE* file);
// 遍历并写入所有对象
void WriteObjects(FILE* file);
// 写入堆转储结束标记
void WriteHeapDumpEnd(FILE* file);
// 当前时间戳(用于Hprof记录)
uint64_t timestamp_;
// 堆内存引用
Heap* heap_;
// 类ID映射表
std::unordered_map<mirror::Class*, uint64_t> class_ids_;
// 对象ID映射表
std::unordered_map<mirror::Object*, uint64_t> object_ids_;
};
bool HprofGenerator::Generate(const std::string& output_path) {
FILE* file = fopen(output_path.c_str(), "wb");
if (!file) {
LOG(ERROR) << "Failed to open output file: " << output_path;
return false;
}
timestamp_ = GetCurrentTimeMicros();
// 写入Hprof文件头
WriteHeader(file);
// 写入堆转储开始标记
WriteHeapDumpStart(file);
// 写入类信息
WriteClasses(file);
// 写入对象信息
WriteObjects(file);
// 写入堆转储结束标记
WriteHeapDumpEnd(file);
fclose(file);
return true;
}
void HprofGenerator::WriteObjects(FILE* file) {
// 遍历堆中的所有对象
heap_->ForEachObject([this, file](mirror::Object* obj) {
// 为对象分配唯一ID
uint64_t object_id = AllocateObjectId(obj);
// 获取对象的类
mirror::Class* clazz = obj->GetClass();
uint64_t class_id = GetClassId(clazz);
// 写入对象记录
HprofRecord record;
record.type = HPROF_RECORD_OBJECT_INSTANCE;
record.timestamp = timestamp_;
record.object_id = object_id;
record.class_id = class_id;
// 写入对象字段值
WriteObjectFields(file, obj, clazz);
// 将记录写入文件
WriteRecord(file, record);
});
}
这个工具对于分析内存泄漏和优化内存使用非常有价值,开发者可以通过分析堆转储文件,了解应用的内存分配情况和对象引用关系。
十三、libnativehelper目录:JNI实现与本地方法
13.1 JNI接口实现
libnativehelper目录实现了Java Native Interface(JNI)的核心功能。JNIEnv结构体的实现位于libnativehelper/JNIHelp.h和JNIHelp.cpp:
// libnativehelper/JNIHelp.h
struct JNIEnv {
/* C++版本的JNI接口函数表 */
const struct JNINativeInterface* functions;
// 从Java对象获取本地引用
jobject NewLocalRef(jobject obj);
// 删除本地引用
void DeleteLocalRef(jobject obj);
// 调用Java方法
jvalue CallVoidMethod(jobject obj, jmethodID methodID, ...);
// 获取Java类
jclass FindClass(const char* name);
// 注册本地方法
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, jint nMethods);
// 其他JNI方法...
};
// libnativehelper/JNIHelp.cpp
jobject JNIEnv::NewLocalRef(jobject obj) {
// 调用底层实现
return functions->NewLocalRef(this, obj);
}
void JNIEnv::DeleteLocalRef(jobject obj) {
functions->DeleteLocalRef(this, obj);
}
jvalue JNIEnv::CallVoidMethod(jobject obj, jmethodID methodID, ...) {
va_list args;
va_start(args, methodID);
jvalue result = functions->CallVoidMethodV(this, obj, methodID, args);
va_end(args);
return result;
}
这个实现为Java代码提供了调用本地C/C++代码的能力,是Android系统中Java层与Native层交互的桥梁。
13.2 本地方法注册
libnativehelper还负责管理Java类与本地方法的映射关系。RegisterMethods函数用于注册本地方法:
// libnativehelper/JNIHelp.cpp
jint RegisterMethods(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods) {
// 查找Java类
jclass clazz = env->FindClass(className);
if (clazz == nullptr) {
LOG(ERROR) << "Native registration unable to find class '" << className << "'";
return JNI_ERR;
}
// 注册本地方法
jint result = env->RegisterNatives(clazz, gMethods, numMethods);
if (result < 0) {
LOG(ERROR) << "RegisterNatives failed for '" << className << "'";
return result;
}
return JNI_OK;
}
// 示例:注册java.lang.String的本地方法
static const JNINativeMethod gStringMethods[] = {
/* name, signature, funcPtr */
{ "nativeCopy", "([CII)Ljava/lang/String;", (void*)String_copy },
{ "nativeGetBytes", "(Ljava/lang/String;)[B", (void*)String_getBytes },
{ "nativeContentEquals", "(Ljava/lang/CharSequence;)Z", (void*)String_contentEquals },
};
int register_java_lang_String(JNIEnv* env) {
return RegisterMethods(env, "java/lang/String", gStringMethods, NELEM(gStringMethods));
}
这种注册机制使得Java类可以无缝调用对应的本地实现,为高性能计算和系统级操作提供了支持。
13.3 JNI异常处理
JNI异常处理机制在libnativehelper/JNIHelp.cpp中实现:
// libnativehelper/JNIHelp.cpp
/**
* 检查并清除JNI异常
*/
bool JNI_CheckAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
if (env->ExceptionCheck()) {
if (methodName) {
LOG(ERROR) << "An exception was thrown by callback '" << methodName << "'.";
}
env->ExceptionDescribe();
env->ExceptionClear();
return true;
}
return false;
}
/**
* 抛出指定类型的Java异常
*/
void JNI_ThrowException(JNIEnv* env, const char* className, const char* msg) {
jclass exceptionClass = env->FindClass(className);
if (exceptionClass == nullptr) {
LOG(ERROR) << "Unable to find exception class " << className;
/* ClassNotFoundException now pending */
return;
}
if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
LOG(ERROR) << "Failed throwing '" << className << "' with message '" << msg << "'";
}
env->DeleteLocalRef(exceptionClass);
}
这些函数确保了在JNI调用过程中发生的异常能够被正确捕获和处理,维护了Java和Native代码之间的异常传播机制。
十四、utils目录:通用工具库
14.1 日志系统实现
utils/Log.h和Log.cpp实现了ART的日志系统:
// utils/Log.h
#ifndef ART_UTILS_LOG_H_
#define ART_UTILS_LOG_H_
#include <cstdarg>
#include <string>
namespace art {
enum LogSeverity {
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_FATAL,
};
// 日志输出函数
void Log(LogSeverity severity, const char* file, int line, const char* fmt, ...);
// 格式化日志消息
std::string FormatLog(const char* file, int line, LogSeverity severity, const char* fmt, va_list args);
// 日志宏定义
#define LOG(severity) ::art::Log(::art::LOG_##severity, __FILE__, __LINE__)
// 条件日志
#define LOG_IF(severity, condition) \
(static_cast<bool>(condition) ? (void)::art::Log(::art::LOG_##severity, __FILE__, __LINE__) : (void)0)
} // namespace art
#endif // ART_UTILS_LOG_H_
// utils/Log.cpp
#include "Log.h"
#include <android/log.h>
#include <cstdio>
#include <ctime>
namespace art {
static const char* kLogTags[] = {
"DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};
void Log(LogSeverity severity, const char* file, int line, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
// 格式化日志消息
std::string message = FormatLog(file, line, severity, fmt, args);
va_end(args);
// 根据日志级别选择输出目标
if (severity == LOG_FATAL) {
__android_log_write(ANDROID_LOG_FATAL, "ART", message.c_str());
// 对于FATAL级别的日志,终止程序
abort();
} else {
int android_log_level = ANDROID_LOG_DEBUG + severity;
__android_log_write(android_log_level, "ART", message.c_str());
}
}
std::string FormatLog(const char* file, int line, LogSeverity severity, const char* fmt, va_list args) {
// 获取文件名(不包含路径)
const char* file_name = strrchr(file, '/');
if (file_name == nullptr) {
file_name = file;
} else {
file_name++; // 跳过斜杠
}
// 格式化时间戳
char time_buffer[32];
time_t now = time(nullptr);
struct tm* tm_info = localtime(&now);
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S", tm_info);
// 格式化日志消息
char message_buffer[1024];
vsnprintf(message_buffer, sizeof(message_buffer), fmt, args);
// 组合完整的日志行
char log_line[2048];
snprintf(log_line, sizeof(log_line), "[%s] %s:%d %s: %s",
time_buffer, file_name, line, kLogTags[severity], message_buffer);
return std::string(log_line);
}
} // namespace art
这个日志系统为ART的开发和调试提供了重要支持,能够记录不同级别的信息,便于问题追踪。
14.2 字符串处理工具
utils/StringPiece.h和StringPiece.cpp提供了高效的字符串处理功能:
// utils/StringPiece.h
#ifndef ART_UTILS_STRING_PIECE_H_
#define ART_UTILS_STRING_PIECE_H_
#include <cstring>
#include <string>
namespace art {
class StringPiece {
public:
// 默认构造函数
StringPiece() : ptr_(nullptr), length_(0) {}
// 从C风格字符串构造
StringPiece(const char* str) : ptr_(str), length_(str ? strlen(str) : 0) {}
// 从字符串和长度构造
StringPiece(const char* ptr, size_t length) : ptr_(ptr), length_(length) {}
// 从std::string构造
StringPiece(const std::string& str) : ptr_(str.data()), length_(str.size()) {}
// 获取字符串指针
const char* data() const { return ptr_; }
// 获取字符串长度
size_t size() const { return length_; }
// 判断是否为空
bool empty() const { return length_ == 0; }
// 转换为std::string
std::string ToString() const {
return std::string(ptr_, length_);
}
// 查找子字符串
size_t find(const StringPiece& substr) const;
// 分割字符串
std::vector<StringPiece> Split(char delimiter) const;
private:
const char* ptr_;
size_t length_;
};
} // namespace art
#endif // ART_UTILS_STRING_PIECE_H_
// utils/StringPiece.cpp
#include "StringPiece.h"
namespace art {
size_t StringPiece::find(const StringPiece& substr) const {
if (substr.empty()) {
return 0;
}
const char* result = std::search(ptr_, ptr_ + length_, substr.ptr_, substr.ptr_ + substr.length_);
return (result == ptr_ + length_) ? std::string::npos : result - ptr_;
}
std::vector<StringPiece> StringPiece::Split(char delimiter) const {
std::vector<StringPiece> result;
const char* start = ptr_;
const char* end = ptr_ + length_;
const char* current = start;
while (current < end) {
if (*current == delimiter) {
// 找到分隔符,添加子字符串
result.emplace_back(start, current - start);
start = current + 1;
}
current++;
}
// 添加最后一个子字符串
result.emplace_back(start, end - start);
return result;
}
} // namespace art
StringPiece类提供了一种轻量级的方式来处理字符串,避免了不必要的内存复制,提高了字符串操作的效率。
14.3 时间和性能测量工具
utils/TimeUtils.h和TimeUtils.cpp实现了时间测量和性能分析工具:
// utils/TimeUtils.h
#ifndef ART_UTILS_TIME_UTILS_H_
#define ART_UTILS_TIME_UTILS_H_
#include <stdint.h>
namespace art {
// 获取当前时间(毫秒)
uint64_t CurrentTimeMillis();
// 获取当前时间(微秒)
uint64_t CurrentTimeMicros();
// 获取当前CPU时间(纳秒)
uint64_t CurrentCpuTimeNanos();
// 性能计时器类
class ScopedTimer {
public:
explicit ScopedTimer(const char* name);
~ScopedTimer();
private:
const char* name_;
uint64_t start_time_;
};
} // namespace art
#endif // ART_UTILS_TIME_UTILS_H_
// utils/TimeUtils.cpp
#include "TimeUtils.h"
#include <time.h>
#include <sys/time.h>
#include <android/log.h>
namespace art {
uint64_t CurrentTimeMillis() {
struct timeval tv;
gettimeofday(&tv, nullptr);
return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
uint64_t CurrentTimeMicros() {
struct timeval tv;
gettimeofday(&tv, nullptr);
return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
uint64_t CurrentCpuTimeNanos() {
struct timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
}
ScopedTimer::ScopedTimer(const char* name) : name_(name) {
start_time_ = CurrentTimeMicros();
}
ScopedTimer::~ScopedTimer() {
uint64_t end_time = CurrentTimeMicros();
uint64_t duration = end_time - start_time_;
__android_log_print(ANDROID_LOG_DEBUG, "ART",
"Timer %s took %.2f ms",
name_, duration / 1000.0);
}
} // namespace art
这些工具对于测量代码执行时间、分析性能瓶颈非常有用,开发者可以使用ScopedTimer轻松测量特定代码段的执行时间。
十五、security目录:安全机制实现
15.1 SELinux集成
security/selinux目录实现了ART与SELinux(Security-Enhanced Linux)的集成。SELinux.cpp文件负责SELinux上下文管理:
// security/selinux/SELinux.cpp
#include "selinux/SELinux.h"
#include <selinux/selinux.h>
#include <log/log.h>
namespace art {
namespace selinux {
// 检查当前SELinux状态
bool IsEnforcing() {
return selinux_status_from_cmdline() == SELINUX_ENFORCING;
}
// 获取当前进程的SELinux上下文
bool GetContext(std::string* context) {
char* raw_context = nullptr;
if (getcon(&raw_context) != 0) {
ALOGE("Failed to get SELinux context: %s", strerror(errno));
return false;
}
*context = std::string(raw_context);
freecon(raw_context);
return true;
}
// 检查是否允许特定的SELinux操作
bool CheckAccess(const std::string& context, const std::string& type, const std::string& perm) {
if (!IsEnforcing()) {
// 如果SELinux未强制实施,默认允许所有操作
return true;
}
// 解析上下文
security_context_t secctx = nullptr;
if (selinux_context_to_sid(context.c_str(), &secctx) != 0) {
ALOGE("Failed to convert context to SID: %s", strerror(errno));
return false;
}
// 检查访问权限
int result = security_check_access(secctx, secctx, type.c_str(), perm.c_str(), nullptr);
selinux_release_sid(secctx);
return (result == 0);
}
} // namespace selinux
} // namespace art
通过SELinux集成,ART能够遵循系统的安全策略,限制对敏感资源的访问,增强了系统的安全性。
15.2 内存安全保护
security/memory目录实现了内存安全相关功能。MemoryProtection.cpp提供了内存保护机制:
// security/memory/MemoryProtection.cpp
#include "memory/MemoryProtection.h"
#include <sys/mman.h>
#include <unistd.h>
#include <log/log.h>
namespace art {
namespace security {
// 保护内存区域,设置特定的访问权限
bool ProtectMemoryRegion(void* address, size_t size, int prot) {
// 确保地址和大小按页对齐
size_t page_size = sysconf(_SC_PAGESIZE);
uintptr_t aligned_addr = (uintptr_t)address & ~(page_size - 1);
size_t aligned_size = ((uintptr_t)address + size - aligned_addr + page_size - 1) & ~(page_size - 1);
// 调用mprotect设置内存保护
if (mprotect((void*)aligned_addr, aligned_size, prot) != 0) {
ALOGE("Failed to protect memory region: %s", strerror(errno));
return false;
}
return true;
}
// 防止内存区域被执行(NX保护)
bool MarkMemoryNoExecute(void* address, size_t size) {
return ProtectMemoryRegion(address, size, PROT_READ | PROT_WRITE);
}
// 使内存区域只读
bool MakeMemoryReadOnly(void* address, size_t size) {
return ProtectMemoryRegion(address, size, PROT_READ);
}
} // namespace security
} // namespace art
这些内存保护机制有助于防止缓冲区溢出攻击和代码注入攻击,保护系统免受恶意代码的侵害。
15.3 代码签名验证
security/signature目录实现了DEX文件的签名验证功能。SignatureVerifier.cpp负责验证应用的数字签名:
// security/signature/SignatureVerifier.cpp
#include "signature/SignatureVerifier.h"
#include <openssl/sha.h>
#include <android-base/strings.h>
#include <log/log.h>
namespace art {
namespace security {
// 验证DEX文件的签名
bool VerifyDexSignature(const std::string& dex_path, const std::vector<std::string>& expected_signatures) {
// 打开DEX文件
FILE* file = fopen(dex_path.c_str(), "rb");
if (!file) {
ALOGE("Failed to open DEX file: %s", dex_path.c_str());
return false;
}
// 计算DEX文件的SHA-256哈希
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
const size_t buffer_size = 8192;
unsigned char buffer[buffer_size];
size_t bytes;
while ((bytes = fread(buffer, 1, buffer_size, file)) != 0) {
SHA256_Update(&sha256, buffer, bytes);
}
SHA256_Final(hash, &sha256);
fclose(file);
// 将哈希转换为十六进制字符串
std::string hash_str;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
char hex[3];
sprintf(hex, "%02x", hash[i]);
hash_str += hex;
}
// 检查计算的哈希是否与预期签名匹配
for (const std::string& expected : expected_signatures) {
if (android::base::StringToLower(hash_str) == android::base::StringToLower(expected)) {
return true;
}
}
ALOGE("Signature verification failed for %s", dex_path.c_str());
return false;
}
} // namespace security
} // namespace art
代码签名验证确保了应用的完整性和来源可信性,防止恶意应用被篡改或伪造。
十六、runtime目录:核心运行时系统(续)
16.4 线程同步机制
runtime/synchronization目录实现了线程同步相关功能。Monitor.cpp提供了Java监视器(synchronized关键字)的底层实现:
// runtime/synchronization/Monitor.cpp
#include "monitor.h"
#include "thread.h"
#include "object.h"
#include "globals.h"
namespace art {
// 进入对象的监视器
void Monitor::Enter(mirror::Object* obj, Thread* self) {
// 获取对象的监视器指针
MonitorPtr monitor = obj->GetMonitor();
// 检查是否已经持有该监视器
if (monitor->IsHeldByCurrentThread(self)) {
// 重入锁,增加递归计数
monitor->IncrementRecursionCount();
return;
}
// 尝试获取锁
if (!monitor->TryEnter(self)) {
// 获取失败,将线程放入等待队列
self->Block();
monitor->AddToWaitQueue(self);
// 线程挂起,等待唤醒
self->WaitForWakeup();
// 线程被唤醒,重新尝试获取锁
monitor->Enter(self);
}
}
// 退出对象的监视器
void Monitor::Exit(mirror::Object* obj, Thread* self) {
// 获取对象的监视器指针
MonitorPtr monitor = obj->GetMonitor();
// 检查是否持有该监视器
if (!monitor->IsHeldByCurrentThread(self)) {
// 抛出IllegalMonitorStateException异常
self->ThrowIllegalMonitorStateException("Attempt to exit monitor without entering");
return;
}
// 减少递归计数
int recursion_count = monitor->DecrementRecursionCount();
// 如果递归计数为0,释放锁
if (recursion_count == 0) {
monitor->Release(self);
// 检查是否有线程在等待该锁
if (!monitor->WaitQueueEmpty()) {
// 唤醒一个等待的线程
Thread* waiting_thread = monitor->RemoveFromWaitQueue();
waiting_thread->Unblock();
waiting_thread->Schedule();
}
}
}
// 使当前线程等待,直到其他线程调用notify()或notifyAll()
void Monitor::Wait(mirror::Object* obj, Thread* self, jlong timeout_ms) {
// 获取对象的监视器指针
MonitorPtr monitor = obj->GetMonitor();
// 检查是否持有该监视器
if (!monitor->IsHeldByCurrentThread(self)) {
// 抛出IllegalMonitorStateException异常
self->ThrowIllegalMonitorStateException("Attempt to wait on monitor without entering");
return;
}
// 保存递归计数并释放锁
int recursion_count = monitor->GetRecursionCount();
monitor->Release(self);
// 将线程放入对象的等待集合
self->Block();
monitor->AddToWaitSet(self);
// 线程挂起,等待唤醒或超时
if (timeout_ms > 0) {
self->WaitForWakeupOrTimeout(timeout_ms);
} else {
self->WaitForWakeup();
}
// 线程被唤醒,重新获取锁
monitor->Enter(self);
// 恢复递归计数
for (int i = 1; i < recursion_count; i++) {
monitor->IncrementRecursionCount();
}
}
// 唤醒在此对象监视器上等待的单个线程
void Monitor::Notify(mirror::Object* obj, Thread* self) {
// 获取对象的监视器指针
MonitorPtr monitor = obj->GetMonitor();
// 检查是否持有该监视器
if (!monitor->IsHeldByCurrentThread(self)) {
// 抛出IllegalMonitorStateException异常
self->ThrowIllegalMonitorStateException("Attempt to notify on monitor without entering");
return;
}
// 检查是否有线程在等待
if (!monitor->WaitSetEmpty()) {
// 从等待集合中移除一个线程
Thread* waiting_thread = monitor->RemoveFromWaitSet();
// 将线程添加到锁的等待队列
monitor->AddToWaitQueue(waiting_thread);
// 唤醒线程
waiting_thread->Unblock();
waiting_thread->Schedule();
}
}
// 唤醒在此对象监视器上等待的所有线程
void Monitor::NotifyAll(mirror::Object* obj, Thread* self) {
// 获取对象的监视器指针
MonitorPtr monitor = obj->GetMonitor();
// 检查是否持有该监视器
if (!monitor->IsHeldByCurrentThread(self)) {
// 抛出IllegalMonitorStateException异常
self->ThrowIllegalMonitorStateException("Attempt to notifyAll on monitor without entering");
return;
}
// 检查是否有线程在等待
if (!monitor->WaitSetEmpty()) {
// 从等待集合中移除所有线程
std::vector<Thread*> waiting_threads = monitor->RemoveAllFromWaitSet();
// 将所有线程添加到锁的等待队列
for (Thread* thread : waiting_threads) {
monitor->AddToWaitQueue(thread);
thread->Unblock();
thread->Schedule();
}
}
}
} // namespace art
这些方法实现了Java同步机制的核心功能,确保多线程环境下的线程安全。
16.5 异常处理机制
runtime/exception目录实现了Java异常处理机制。ThrowLocation.h和Exception.cpp提供了异常抛出和处理的核心功能:
// runtime/exception/ThrowLocation.h
#ifndef ART_RUNTIME_EXCEPTION_THROW_LOCATION_H_
#define ART_RUNTIME_EXCEPTION_THROW_LOCATION_H_
#include <string>
namespace art {
class ThrowLocation {
public:
// 默认构造函数
ThrowLocation() : file_(nullptr), line_(0) {}
// 带位置信息的构造函数
ThrowLocation(const char* file, int line) : file_(file), line_(line) {}
// 是否有有效的位置信息
bool Valid() const { return file_ != nullptr; }
// 获取文件名
const char* File() const { return file_; }
// 获取行号
int Line() const { return line_; }
// 转换为字符串表示
std::string ToString() const;
private:
const char* file_;
int line_;
};
} // namespace art
#endif // ART_RUNTIME_EXCEPTION_THROW_LOCATION_H_
// runtime/exception/Exception.cpp
#include "exception.h"
#include "thread.h"
#include "object-inl.h"
#include "class_linker.h"
#include "dex_file.h"
namespace art {
// 抛出异常
bool Thread::Throw(mirror::Throwable* exception, const ThrowLocation& location) {
// 检查线程是否已经有挂起的异常
if (ExceptionCheck()) {
LOG(WARNING) << "Discarding pending exception (" << GetException()->PrettyTypeOf()
<< ") to throw " << exception->PrettyTypeOf();
// 清除当前异常
ClearException();
}
// 设置异常和抛出位置
SetException(exception);
SetExceptionLocation(location);
// 填充异常堆栈轨迹
FillInStackTrace(exception);
// 开始异常传播
return HandleException();
}
// 填充异常堆栈轨迹
void Thread::FillInStackTrace(mirror::Throwable* exception) {
// 获取当前线程的调用栈
StackVisitor visitor(this, nullptr);
// 跳过Throw()方法本身
visitor.SkipFrames(1);
// 创建堆栈轨迹元素数组
StackHandleScope<1> hs(this);
Handle<mirror::ObjectArray<mirror::StackTraceElement>> stack_trace =
hs.NewHandle(CreateStackTraceArray
16.5 异常处理机制
// runtime/exception/Exception.cpp
// 填充异常堆栈轨迹
void Thread::FillInStackTrace(mirror::Throwable* exception) {
// 获取当前线程的调用栈
StackVisitor visitor(this, nullptr);
// 跳过Throw()方法本身
visitor.SkipFrames(1);
// 创建堆栈轨迹元素数组
StackHandleScope<1> hs(this);
Handle<mirror::ObjectArray<mirror::StackTraceElement>> stack_trace =
hs.NewHandle(CreateStackTraceArray());
// 遍历调用栈,填充堆栈轨迹元素
while (visitor.HasMoreFrames()) {
StackFrameInfo frame_info;
visitor.GetNextFrame(&frame_info);
// 获取方法所属类的名称
const DexFile* dex_file = frame_info.dex_file;
const DexFile::ClassDef& class_def = dex_file->GetClassDef(frame_info.class_def_idx);
std::string class_name = dex_file->StringByTypeIndex(class_def.type_idx).c_str();
// 获取方法名称
const DexFile::Method& method = dex_file->GetMethod(frame_info.method_idx);
std::string method_name = dex_file->StringByIndex(method.name_idx).c_str();
// 创建StackTraceElement对象
Handle<mirror::StackTraceElement> element =
hs.NewHandle(CreateStackTraceElement(class_name, method_name, frame_info.file_name, frame_info.line_number));
// 将元素添加到堆栈轨迹数组
stack_trace->SetElementAt(element.Get(), stack_trace->Length() - 1);
}
// 设置异常的堆栈轨迹
exception->SetStackTrace(stack_trace.Get());
}
// 处理异常
bool Thread::HandleException() {
// 从当前方法开始向上查找异常处理代码
StackVisitor visitor(this, nullptr);
while (visitor.HasMoreFrames()) {
StackFrameInfo frame_info;
visitor.GetNextFrame(&frame_info);
// 检查方法是否有异常处理表
const DexFile::CodeItem& code_item = frame_info.dex_file->GetCodeItem(frame_info.method_idx);
const uint8* insns = code_item.insns;
const ExceptionHandler* handlers = code_item.exceptionHandlers;
uint32_t handler_count = code_item.exceptionHandlerCount;
// 查找匹配的异常处理代码
for (uint32_t i = 0; i < handler_count; ++i) {
const ExceptionHandler& handler = handlers[i];
if (IsExceptionCaughtByHandler(GetException(), handler)) {
// 找到匹配的异常处理代码,调整程序计数器
visitor.SetProgramCounter(handler.handlerPc);
// 执行异常处理代码
return true;
}
}
}
// 没有找到异常处理代码,向上层抛出异常
return false;
}
// 判断异常是否被指定的异常处理器捕获
bool Thread::IsExceptionCaughtByHandler(mirror::Throwable* exception, const ExceptionHandler& handler) {
// 获取异常的类型
mirror::Class* exception_class = exception->GetClass();
// 检查异常类型是否与异常处理器匹配
if (handler.catchType == kCatchAll) {
return true;
}
const DexFile* dex_file = handler.dexFile;
const TypeIndex catch_type_idx = dex_file->GetExceptionHandlerCatchType(handler);
mirror::Class* catch_class = GetClassLinker()->FindClass(dex_file->StringByTypeIndex(catch_type_idx).c_str());
return catch_class->IsAssignableFrom(exception_class);
}
上述代码实现了ART中Java异常处理的核心逻辑。FillInStackTrace方法负责收集异常发生时的调用栈信息,生成详细的堆栈轨迹;HandleException方法则从当前方法开始,逐层向上查找是否存在能够处理该异常的代码块;IsExceptionCaughtByHandler方法用于判断异常是否能被特定的异常处理器捕获,确保异常处理的准确性。
16.6 动态链接与JNI调用优化
在runtime/native目录中,ART对JNI调用和动态链接进行了深度优化。JniInvocation.cpp文件负责管理JNI调用的入口点和动态链接过程:
// runtime/native/JniInvocation.cpp
#include "JniInvocation.h"
#include "JNIHelp.h"
#include "class_linker.h"
#include "jni_internal.h"
#include "thread.h"
namespace art {
// 解析JNI方法的本地实现
void* JniInvocation::FindNativeMethod(const char* class_name, const char* method_name, const char* sig) {
// 查找Java类
Thread* self = Thread::Current();
ClassLinker* linker = self->GetClassLinker();
Handle<mirror::Class> clazz = linker->FindClass(self, class_name);
if (clazz == nullptr) {
return nullptr;
}
// 查找方法ID
jmethodID method_id = self->GetJniEnv()->GetMethodID(clazz.Get(), method_name, sig);
if (method_id == nullptr) {
return nullptr;
}
// 获取方法的本地实现指针
return self->GetJniEnv()->FromReflectedMethod(method_id);
}
// 动态链接JNI方法
bool JniInvocation::LinkNativeMethod(const char* class_name, const char* method_name, const char* sig, void* fnPtr) {
Thread* self = Thread::Current();
ClassLinker* linker = self->GetClassLinker();
Handle<mirror::Class> clazz = linker->FindClass(self, class_name);
if (clazz == nullptr) {
return false;
}
// 查找方法ID
jmethodID method_id = self->GetJniEnv()->GetMethodID(clazz.Get(), method_name, sig);
if (method_id == nullptr) {
return false;
}
// 设置方法的本地实现指针
return self->GetJniEnv()->SetMethodNativeMethod(method_id, fnPtr);
}
// 调用JNI方法
jvalue JniInvocation::CallJniMethod(const char* class_name, const char* method_name, const char* sig, ...) {
Thread* self = Thread::Current();
void* method_ptr = FindNativeMethod(class_name, method_name, sig);
if (method_ptr == nullptr) {
LOG(ERROR) << "Native method not found: " << class_name << "->" << method_name << sig;
return JValue::FromInt(0);
}
// 解析方法签名,确定参数和返回值类型
JniMethodInfo method_info;
if (!GetJniMethodInfo(sig, &method_info)) {
LOG(ERROR) << "Invalid method signature: " << sig;
return JValue::FromInt(0);
}
// 准备参数
va_list args;
va_start(args, sig);
std::vector<JValue> param_values;
for (size_t i = 0; i < method_info.arg_count; ++i) {
param_values.push_back(GetJniArgValue(method_info.arg_types[i], args));
}
va_end(args);
// 调用JNI方法
jvalue result;
if (method_info.fp_jni_void == nullptr) {
result = InvokeJniMethod(method_ptr, ¶m_values[0], method_info.arg_count, method_info.return_type);
} else {
// 对于void返回类型的方法,单独处理
method_info.fp_jni_void(¶m_values[0], method_info.arg_count);
result = JValue::FromInt(0);
}
return result;
}
FindNativeMethod方法通过类名、方法名和签名查找JNI方法的本地实现;LinkNativeMethod用于将JNI方法与具体的本地函数指针绑定;CallJniMethod则负责解析方法签名,准备参数并执行JNI方法调用。这些优化措施减少了JNI调用的开销,提高了Java层与Native层交互的效率。
十七、compiler目录:编译系统(续)
17.1 中间表示(IR)优化策略深化
在compiler/optimizing目录中,ART对中间表示(HGraph)的优化策略极为丰富。以循环优化为例,LoopOptimizer.cpp文件中的代码负责识别和优化循环结构:
// compiler/optimizing/LoopOptimizer.cpp
#include "LoopOptimizer.h"
#include "h_graph.h"
#include "h_graph_inliner.h"
#include "h_value.h"
namespace art {
namespace optimizing {
// 查找HGraph中的所有循环
void LoopOptimizer::FindLoops(HGraph* graph) {
// 使用深度优先搜索标记循环边界
graph->ForEachBlock([this](HBasicBlock* block) {
if (block->HasLoopHeader()) {
HLoop* loop = block->GetLoop();
if (loop != nullptr) {
loops_.insert(loop);
}
}
});
}
// 循环不变代码外提
void LoopOptimizer::HoistLoopInvariantCode(HLoop* loop) {
// 遍历循环中的所有基本块
for (HBasicBlock* block : loop->GetBlocks()) {
block->ForEachInstruction([this, loop](HInstruction* inst) {
// 判断指令是否为循环不变代码
if (IsLoopInvariant(inst, loop)) {
// 找到合适的前置块作为外提目标
HBasicBlock* target_block = FindPreheaderBlock(loop);
if (target_block != nullptr) {
// 将指令移动到前置块
inst->MoveBeforeInsertingInto(target_block->GetLastInstruction());
}
}
});
}
}
// 循环展开
void LoopOptimizer::UnrollLoops(HLoop* loop) {
// 设置展开因子
const int unroll_factor = 4;
for (int i = 0; i < unroll_factor; ++i) {
// 复制循环体中的基本块和指令
std::vector<HBasicBlock*> new_blocks;
for (HBasicBlock* block : loop->GetBlocks()) {
HBasicBlock* new_block = block->Clone();
new_blocks.push_back(new_block);
}
// 调整复制后基本块的跳转关系
for (size_t j = 0; j < new_blocks.size(); ++j) {
HBasicBlock* cur_block = new_blocks[j];
for (HBasicBlock* succ : cur_block->GetSuccessors()) {
size_t succ_index = FindBlockIndex(loop->GetBlocks(), succ);
cur_block->ReplaceSuccessor(succ, new_blocks[succ_index]);
}
}
// 将展开后的循环体连接到原循环
HBasicBlock* loop_header = loop->GetHeader();
HBasicBlock* last_block = new_blocks.back();
last_block->AddSuccessor(loop_header);
}
}
// 执行循环优化
void LoopOptimizer::OptimizeLoops(HGraph* graph) {
FindLoops(graph);
for (HLoop* loop : loops_) {
HoistLoopInvariantCode(loop);
UnrollLoops(loop);
}
}
} // namespace optimizing
} // namespace art
FindLoops方法通过深度优先搜索定位HGraph中的循环结构;HoistLoopInvariantCode将循环不变代码外提到前置块,减少循环内的重复计算;UnrollLoops根据设定的展开因子复制循环体,减少循环跳转开销。这些优化策略显著提升了循环密集型代码的执行效率。
17.2 机器码生成与架构适配
在compiler/backend目录下,针对不同硬件架构的机器码生成是关键任务。以ARM64架构为例,arm64/Arm64InstructionSelector.cpp文件负责将优化后的HGraph指令转换为ARM64汇编指令:
// compiler/backend/arm64/Arm64InstructionSelector.cpp
#include "Arm64InstructionSelector.h"
#include "arm64_instruction_builder.h"
#include "h_graph.h"
#include "h_value.h"
namespace art {
namespace arm64 {
// 选择合适的ARM64指令来实现HInstruction
void Arm64InstructionSelector::Select(HInstruction* inst) {
switch (inst->GetKind()) {
case HInstruction::kAdd: {
HValue* left = inst->InputAt(0);
HValue* right = inst->InputAt(1);
HValue* result = inst->OutputAt(0);
// 将加法操作转换为ARM64的ADD指令
Arm64InstructionBuilder builder;
builder.BuildAddInstruction(left, right, result);
break;
}
case HInstruction::kLoad: {
HValue* address = inst->InputAt(0);
HValue* result = inst->OutputAt(0);
// 将加载操作转换为ARM64的LDR指令
Arm64InstructionBuilder builder;
builder.BuildLoadInstruction(address, result);
break;
}
case HInstruction::kStore: {
HValue* value = inst->InputAt(0);
HValue* address = inst->InputAt(1);
// 将存储操作转换为ARM64的STR指令
Arm64InstructionBuilder builder;
builder.BuildStoreInstruction(value, address);
break;
}
// 其他指令类型的处理...
default:
LOG(FATAL) << "Unsupported instruction kind: " << inst->GetKind();
}
}
// 为HGraph生成ARM64机器码
void Arm64InstructionSelector::GenerateMachineCode(HGraph* graph) {
graph->ForEachBlock([this](HBasicBlock* block) {
block->ForEachInstruction([this](HInstruction* inst) {
Select(inst);
});
});
}
} // namespace arm64
} // namespace art
Select方法根据HInstruction的类型,调用Arm64InstructionBuilder生成对应的ARM64汇编指令;GenerateMachineCode则遍历整个HGraph,将所有指令转换为机器码。通过这种方式,ART实现了对ARM64架构的高效适配,确保生成的机器码能在该架构设备上高效运行。
17.3 编译驱动与任务调度
compiler/runtime目录中的CompilationDriver.cpp文件负责管理编译任务的调度和执行:
// compiler/runtime/CompilationDriver.cpp
#include "CompilationDriver.h"
#include "compiler_callbacks.h"
#include "runtime.h"
#include "thread.h"
namespace art {
// 初始化编译驱动
void CompilationDriver::Initialize(Runtime* runtime) {
runtime_ = runtime;
// 创建编译任务队列
compilation_queue_ = std::make_unique<CompilationQueue>();
// 启动编译线程
compilation_thread_ = std::thread(&CompilationDriver::CompileTasks, this);
}
// 将编译任务添加到队列
void CompilationDriver::AddTask(CompilationUnit* unit) {
compilation_queue_->Push(unit);
}
// 编译任务执行线程
void CompilationDriver::CompileTasks() {
while (true) {
// 从队列中获取编译任务
CompilationUnit* unit = compilation_queue_->Pop();
if (unit == nullptr) {
// 队列为空,等待新任务
std::unique_lock<std::mutex> lock(task_mutex_);
task_available_.wait(lock, [this]{ return!compilation_queue_->IsEmpty(); });
continue;
}
// 执行编译任务
CompilerCallbacks callbacks(unit);
unit->Compile(&callbacks);
// 通知运行时编译完成
runtime_->NotifyCompilationFinished(unit);
// 释放编译单元资源
delete unit;
}
}
// 停止编译驱动
void CompilationDriver::Shutdown() {
// 停止编译线程
compilation_thread_.join();
}
} // namespace art
Initialize方法完成编译驱动的初始化,包括创建任务队列和启动编译线程;AddTask用于将待编译的任务(如某个方法的编译单元)加入队列;CompileTasks作为编译线程的执行函数,不断从队列中取出任务并执行编译,完成后通知运行时并释放资源。这种任务调度机制确保了编译过程的高效和有序进行。
十八、dex目录:DEX文件处理(续)
18.1 DEX文件格式扩展与兼容性处理
随着Android系统的发展,DEX文件格式也在不断演进。在dex/DexFileFormat.h和DexFileFormat.cpp中,ART对DEX文件格式的兼容性和扩展性进行了处理:
// dex/DexFileFormat.h
#ifndef ART_DEX_DEX_FILE_FORMAT_H_
#define ART_DEX_DEX_FILE_FORMAT_H_
#include <cstdint>
#include <string>
#include <vector>
namespace art {
// 定义DEX文件格式版本
enum class DexFileFormatVersion {
kDex035 = 0x035,
kDex036 = 0x036,
// 其他版本...
};
// DEX文件头结构
struct DexFileHeader {
uint8_t magic[8]; // 魔数,用于标识文件类型
uint32_t checksum; //
// dex/DexFileFormat.h
// DEX文件头结构
struct DexFileHeader {
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; // 字节序标记
uint32_t link_size; // 链接段大小
uint32_t link_off; // 链接段偏移
uint32_t map_off; // 映射表偏移
uint32_t string_ids_size; // 字符串ID数量
uint32_t string_ids_off; // 字符串ID表偏移
uint32_t type_ids_size; // 类型ID数量
uint32_t type_ids_off; // 类型ID表偏移
uint32_t proto_ids_size; // 原型ID数量
uint32_t proto_ids_off; // 原型ID表偏移
uint32_t field_ids_size; // 字段ID数量
uint32_t field_ids_off; // 字段ID表偏移
uint32_t method_ids_size; // 方法ID数量
uint32_t method_ids_off; // 方法ID表偏移
uint32_t class_defs_size; // 类定义数量
uint32_t class_defs_off; // 类定义表偏移
uint32_t data_size; // 数据段大小
uint32_t data_off; // 数据段偏移
};
// 检查DEX文件格式版本是否兼容
bool IsDexVersionSupported(uint32_t version);
// 获取DEX文件格式版本字符串
std::string GetDexVersionString(uint32_t version);
} // namespace art
#endif // ART_DEX_DEX_FILE_FORMAT_H_
// dex/DexFileFormat.cpp
#include "DexFileFormat.h"
#include <string>
#include <vector>
namespace art {
// 支持的DEX文件版本列表
static const std::vector<uint32_t> kSupportedDexVersions = {
0x035, // DEX 035
0x036, // DEX 036
0x037, // DEX 037
0x038, // DEX 038 (Android 8.0+)
};
// 检查DEX文件格式版本是否兼容
bool IsDexVersionSupported(uint32_t version) {
for (uint32_t supported_version : kSupportedDexVersions) {
if (version == supported_version) {
return true;
}
}
return false;
}
// 获取DEX文件格式版本字符串
std::string GetDexVersionString(uint32_t version) {
char buffer[16];
snprintf(buffer, sizeof(buffer), "%.3f", version / 100.0f);
return std::string(buffer);
}
} // namespace art
上述代码展示了DEX文件头结构的定义以及版本兼容性检查机制。通过维护一个支持的版本列表,ART能够识别并处理不同版本的DEX文件,确保应用的向后兼容性。当遇到不支持的版本时,系统会抛出相应的异常,提示用户进行必要的更新。
18.2 DEX文件优化与OAT文件生成
dex/opt目录中的代码负责将DEX文件优化并转换为OAT(Optimized Android Archive)文件。OatWriter.cpp实现了OAT文件的生成逻辑:
// dex/opt/OatWriter.cpp
#include "OatWriter.h"
#include "DexFile.h"
#include "OatFile.h"
#include "oat.h"
namespace art {
// 初始化OAT写入器
OatWriter::OatWriter(const std::string& oat_filename, const std::vector<const DexFile*>& dex_files)
: oat_filename_(oat_filename), dex_files_(dex_files) {
// 初始化OAT文件头
oat_header_.magic[0] = 'o';
oat_header_.magic[1] = 'a';
oat_header_.magic[2] = 't';
oat_header_.magic[3] = '\n';
oat_header_.version[0] = '0';
oat_header_.version[1] = 'A';
oat_header_.version[2] = 'T';
oat_header_.version[3] = '0';
oat_header_.instruction_set = kRuntimeISA;
oat_header_.instruction_set_features_bitmap = GetInstructionSetFeatures();
oat_header_.dex_file_count = dex_files_.size();
// 其他头字段初始化...
}
// 写入OAT文件
bool OatWriter::Write() {
// 打开输出文件
FILE* file = fopen(oat_filename_.c_str(), "wb");
if (file == nullptr) {
LOG(ERROR) << "Failed to open OAT file: " << oat_filename_;
return false;
}
// 写入OAT文件头
size_t written = fwrite(&oat_header_, sizeof(oat_header_), 1, file);
if (written != 1) {
LOG(ERROR) << "Failed to write OAT header";
fclose(file);
return false;
}
// 写入DEX文件信息
for (const DexFile* dex_file : dex_files_) {
OatDexFile oat_dex_file;
oat_dex_file.location_size = dex_file->GetLocation().size();
oat_dex_file.location_data = dex_file->GetLocation().c_str();
oat_dex_file.checksum = dex_file->GetHeader().checksum;
// 其他DEX文件信息...
// 写入DEX文件位置信息
written = fwrite(&oat_dex_file.location_size, sizeof(oat_dex_file.location_size), 1, file);
written += fwrite(oat_dex_file.location_data, oat_dex_file.location_size, 1, file);
written += fwrite(&oat_dex_file.checksum, sizeof(oat_dex_file.checksum), 1, file);
// 其他信息写入...
if (written != 3) {
LOG(ERROR) << "Failed to write OAT DEX file entry";
fclose(file);
return false;
}
}
// 为每个DEX文件生成并写入优化后的代码
for (const DexFile* dex_file : dex_files_) {
// 优化DEX文件
std::vector<uint8_t> optimized_code = OptimizeDexFile(dex_file);
// 写入优化后的代码大小
uint32_t code_size = optimized_code.size();
written = fwrite(&code_size, sizeof(code_size), 1, file);
if (written != 1) {
LOG(ERROR) << "Failed to write optimized code size";
fclose(file);
return false;
}
// 写入优化后的代码
written = fwrite(optimized_code.data(), code_size, 1, file);
if (written != 1) {
LOG(ERROR) << "Failed to write optimized code";
fclose(file);
return false;
}
}
// 写入OAT文件尾部信息
// ...
fclose(file);
return true;
}
// 优化DEX文件
std::vector<uint8_t> OatWriter::OptimizeDexFile(const DexFile* dex_file) {
// 创建优化器
DexOptimizer optimizer(dex_file);
// 执行优化
if (!optimizer.Optimize()) {
LOG(ERROR) << "Failed to optimize DEX file";
return std::vector<uint8_t>();
}
// 获取优化后的DEX文件数据
return optimizer.GetOptimizedData();
}
} // namespace art
OatWriter类负责将一个或多个DEX文件转换为OAT文件。在初始化阶段,它设置OAT文件头的基本信息,包括魔数、版本号和指令集等;Write方法将这些信息写入文件,并为每个DEX文件生成优化后的代码;OptimizeDexFile调用DexOptimizer对DEX文件进行优化,如方法内联、常量传播等。这种优化处理能够显著提升应用的执行效率。
18.3 DEX文件验证与安全性检查
dex/verifier目录中的代码负责验证DEX文件的合法性和安全性。DexVerifier.cpp实现了主要的验证逻辑:
// dex/verifier/DexVerifier.cpp
#include "DexVerifier.h"
#include "DexFile.h"
#include "verifier_errors.h"
namespace art {
namespace verifier {
// 验证DEX文件
bool DexVerifier::Verify(const DexFile& dex_file, bool is_compiling) {
// 验证文件头
if (!VerifyHeader(dex_file)) {
return false;
}
// 验证字符串表
if (!VerifyStringIds(dex_file)) {
return false;
}
// 验证类型表
if (!VerifyTypeIds(dex_file)) {
return false;
}
// 验证原型表
if (!VerifyProtoIds(dex_file)) {
return false;
}
// 验证字段表
if (!VerifyFieldIds(dex_file)) {
return false;
}
// 验证方法表
if (!VerifyMethodIds(dex_file)) {
return false;
}
// 验证类定义
if (!VerifyClassDefs(dex_file)) {
return false;
}
// 验证代码项
if (!VerifyCodeItems(dex_file)) {
return false;
}
// 验证注解
if (!VerifyAnnotations(dex_file)) {
return false;
}
// 其他验证...
return true;
}
// 验证DEX文件头
bool DexVerifier::VerifyHeader(const DexFile& dex_file) {
const DexFile::Header& header = dex_file.GetHeader();
// 验证魔数
if (memcmp(header.magic, DexFile::kDexMagic, sizeof(DexFile::kDexMagic)) != 0) {
LOG(ERROR) << "Invalid DEX file magic";
error_code_ = VERIFICATION_ERROR_BAD_MAGIC;
return false;
}
// 验证版本
uint32_t version = dex_file.GetVersion();
if (!IsDexVersionSupported(version)) {
LOG(ERROR) << "Unsupported DEX file version: " << version;
error_code_ = VERIFICATION_ERROR_BAD_VERSION;
return false;
}
// 验证文件大小
if (header.file_size < sizeof(DexFile::Header)) {
LOG(ERROR) << "Invalid DEX file size";
error_code_ = VERIFICATION_ERROR_BAD_FILE_SIZE;
return false;
}
// 其他头字段验证...
return true;
}
// 验证类定义
bool DexVerifier::VerifyClassDefs(const DexFile& dex_file) {
uint32_t class_defs_size = dex_file.GetHeader().class_defs_size;
uint32_t class_defs_off = dex_file.GetHeader().class_defs_off;
// 检查类定义表偏移是否有效
if (class_defs_off + class_defs_size * sizeof(DexFile::ClassDef) > dex_file.GetHeader().file_size) {
LOG(ERROR) << "Class defs table out of bounds";
error_code_ = VERIFICATION_ERROR_BAD_CLASS_DEFS;
return false;
}
// 验证每个类定义
for (uint32_t i = 0; i < class_defs_size; ++i) {
const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
// 验证类访问标志
if (!VerifyClassAccessFlags(class_def.access_flags)) {
LOG(ERROR) << "Invalid class access flags for class at index " << i;
error_code_ = VERIFICATION_ERROR_BAD_ACCESS_FLAGS;
return false;
}
// 验证类类型
if (!VerifyClassType(dex_file, class_def)) {
LOG(ERROR) << "Invalid class type for class at index " << i;
error_code_ = VERIFICATION_ERROR_BAD_CLASS_TYPE;
return false;
}
// 验证父类
if (!VerifySuperClass(dex_file, class_def)) {
LOG(ERROR) << "Invalid super class for class at index " << i;
error_code_ = VERIFICATION_ERROR_BAD_SUPER_CLASS;
return false;
}
// 验证接口
if (!VerifyInterfaces(dex_file, class_def)) {
LOG(ERROR) << "Invalid interfaces for class at index " << i;
error_code_ = VERIFICATION_ERROR_BAD_INTERFACES;
return false;
}
// 验证源文件
if (!VerifySourceFile(dex_file, class_def)) {
LOG(ERROR) << "Invalid source file for class at index " << i;
error_code_ = VERIFICATION_ERROR_BAD_SOURCE_FILE;
return false;
}
}
return true;
}
} // namespace verifier
} // namespace art
Verify方法作为入口点,依次调用多个验证函数对DEX文件的各个部分进行检查。VerifyHeader验证文件头的魔数、版本和大小等基本信息;VerifyClassDefs则详细检查每个类定义的合法性,包括访问标志、类类型、父类和接口等。通过这些验证,ART能够确保执行的DEX文件符合规范,防止恶意代码的注入和执行。
十九、libcore目录:Java核心库本地实现(续)
19.1 集合框架性能优化
在libcore/java/util目录中,Android对Java集合框架进行了多处性能优化。以ArrayList为例,其本地实现针对移动设备的内存特性进行了优化:
// libcore/java/util/ArrayList.java
package java.util;
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
// 空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
// 存储ArrayList元素的数组
transient Object[] elementData;
// ArrayList的大小(包含的元素个数)
private int size;
// 构造一个具有指定初始容量的空列表
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0) {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
this.elementData = new Object[initialCapacity];
}
// 构造一个初始容量为10的空列表
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
// 将元素添加到列表末尾
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保数组容量足够
elementData[size++] = e;
return true;
}
// 在指定位置插入元素
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // 确保数组容量足够
// 将index及其之后的元素向后移动一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
// 确保内部容量足够
private void ensureCapacityInternal(int minCapacity) {
// 如果数组是默认的空数组,使用默认容量
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
// 明确确保容量
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果需要的最小容量大于当前数组长度,进行扩容
if (minCapacity - elementData.length > 0) {
grow(minCapacity);
}
}
// 数组最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 数组扩容
private void grow(int minCapacity) {
// 获取旧容量
int oldCapacity = elementData.length;
// 新容量为旧容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新容量小于需要的最小容量,直接使用最小容量
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
// 如果新容量大于最大数组容量,处理溢出情况
if (newCapacity - MAX_ARRAY_SIZE > 0) {
newCapacity = hugeCapacity(minCapacity);
}
// 使用Arrays.copyOf进行数组复制,这是一个本地方法,性能高效
elementData = Arrays.copyOf(elementData, newCapacity);
}
// 处理极大容量请求
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) {
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
// 移除指定位置的元素
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
// 计算需要移动的元素个数
int numMoved = size - index - 1;
if (numMoved > 0) {
// 将index之后的元素向前移动一位
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
}
// 清除最后一个位置的引用,帮助垃圾回收
elementData[--size] = null;
return oldValue;
}
// 其他方法...
}
Android版本的ArrayList在多个方面进行了优化:首先,它使用System.arraycopy这个本地方法来实现元素的批量移动,这比使用循环逐个移动元素要高效得多;其次,扩容策略采用1.5倍增长,平衡了内存使用和扩容次数;此外,在元素移除后,及时将末尾元素置为null,帮助垃圾回收器回收不再使用的对象,减少内存占用。
19.2 I/O操作优化
在libcore/java/io目录中,Android对Java的I/O操作进行了优化,特别是针对移动设备的特性。以FileInputStream为例:
// libcore/java/io/FileInputStream.java
package java.io;
public class FileInputStream extends InputStream {
// 文件描述符
private final FileDescriptor fd;
// 文件路径
private final String path;
// 用于关闭文件的引用
private final FileChannel channel;
// 用于本地方法的文件句柄
private long handle;
// 构造函数
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
// 构造函数
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
handle = open(name);
channel = FileChannelImpl.open(fd, name, true, false, this);
}
// 本地方法:打开文件
private native long open(String name) throws FileNotFoundException;
// 本地方法:读取一个字节
public native int read() throws IOException;
// 读取多个字节到字节数组
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
// 本地方法:读取多个字节到字节数组的指定位置
public native int readBytes(byte b[], int off, int len) throws IOException;
// 本地方法:跳过指定数量的字节
public native long skip(long n) throws IOException;
// 返回文件的估计剩余字节数
public native int available() throws IOException;
// 本地方法:关闭文件
private native void close0() throws IOException;
// 关闭文件流
public void close() throws IOException {
synchronized (this) {
if (handle == -1) {
return;
}
FileDescriptor currentFD = fd;
fd = null;
long currentHandle = handle;
handle = -1;
try {
close0();
} finally {
// 关闭文件通道
if (channel != null) {
channel.close();
}
// 释放文件描述符
currentFD.closeAll(new Closeable() {
public void close() throws IOException {
// 这里会调用本地方法释放资源
}
});
}
}
}
// 获取文件描述符
public final FileDescriptor getFD() throws IOException {
if (fd == null) {
throw new IOException();
}
return fd;
}
// 获取文件通道
public FileChannel getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, false, this);
}
return channel;
}
}
// 确保资源被释放
protected void finalize() throws IOException {
if (handle != -1) {
// 调用close方法确保文件被关闭
close();
}
}
// 其他方法...
}
Android的FileInputStream通过本地方法实现了核心的I/O操作,如open、read、readBytes等。这些本地方法直接与操作系统的文件系统交互,避免了Java层的额外开销,提高了I/O操作的效率。此外,它还实现了文件通道(FileChannel)支持,允许更高效的文件操作,特别是在进行大文件读写时。
19.3 并发库优化
在libcore/java/util/concurrent目录中,Android对Java并发库进行了优化,以适应移动设备的多核环境。以ThreadPoolExecutor为例:
// libcore/java/util/concurrent/ThreadPoolExecutor.java
package java.util.concurrent;
public class ThreadPoolExecutor extends AbstractExecutorService {
// 线程池状态和线程数量的原子变量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 线程数量的位数
private static final int COUNT_BITS = Integer.SIZE - 3;
// 最大线程数量
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// 线程池状态
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
// 工作队列
private final BlockingQueue<Runnable> workQueue;
// 线程工厂
private volatile ThreadFactory threadFactory;
// 拒绝执行处理器
private volatile RejectedExecutionHandler handler;
// 线程空闲时间
private volatile long keepAliveTime;
// 是否允许核心线程超时
private volatile boolean allowCoreThreadTimeOut;
// 核心线程数量
private volatile int corePoolSize;
// 最大线程数量
private volatile int maximumPoolSize;
// 默认的拒绝执行处理器
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
// 构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
// 构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0) {
throw new IllegalArgumentException();
}
if (workQueue == null || threadFactory == null || handler == null) {
throw new NullPointerException();
}
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
// 执行任务
public void execute(Runnable command) {
if (command == null) {
throw new NullPointerException();
}
int c = ctl.get();
// 如果当前线程数量小于核心线程数量,创建新线程执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) {
return;
}
c = ctl.get();
}
// 如果线程池处于运行状态,将任务放入工作队列
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 再次检查线程池状态,如果不是运行状态,移除任务并拒绝执行
if (!isRunning(recheck) && remove(command)) {
reject(command);
}
// 如果线程数量为0,创建一个线程
else if (workerCountOf(recheck) == 0) {
addWorker(null, false);
}
}
// 如果无法将任务放入队列,尝试创建新线程
else if (!addWorker(command, false)) {
// 如果创建新线程失败,拒绝执行任务
reject(command);
}
}
// 添加工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 检查线程池状态和队列状态
if (rs >= SHUTDOWN &&
!(rs == SHUTDOWN &&
firstTask == null &&
!workQueue.isEmpty())) {
return false;
}
for (;;) {
int wc = workerCountOf(c);
// 检查线程数量是否超过限制
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) {
return false;
}
// 尝试增加线程数量
if (compareAndIncrementWorkerCount(c)) {
break retry;
}
// 线程数量增加失败,重新读取ctl
c = ctl.get();
// 如果线程池状态已改变,重新开始外层循环
if (runStateOf(c) != rs) {
continue retry;
}
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
// 创建新的工作线程
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 再次检查线程池状态
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) {
throw new IllegalThreadStateException();
}
// 将工作线程添加到集合中
workers.add(w);
int s = workers.size();
if (s > largestPoolSize) {
largestPoolSize = s;
}
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 如果工作线程已添加,启动线程
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
// 如果工作线程启动失败,进行清理
if (!workerStarted) {
addWorkerFailed(w);
}
}
return workerStarted;
}
// 其他方法...
}
Android的ThreadPoolExecutor通过以下方式进行了优化:首先,使用AtomicInteger类型的ctl变量来原子性地管理线程池状态和线程数量,减少了锁的使用,提高了并发性能;其次,通过合理的线程创建和回收策略,平衡了线程数量和系统资源消耗;此外,它还支持核心线程超时机制,允许核心线程在空闲时也能被回收,进一步优化了资源使用