oat文件
Android运行时ART的核心是OAT文件。
OAT文件是一种Android私有ELF文件格式,它不仅包含有从DEX文件翻译而来的本地机器指令,还包含有原来的DEX文件内容。
这样无需重新编译原有的APK就可以让它正常地在ART里面运行,也就是我们不需要改变原来的APK编程接口。
作为Android私有的一种ELF文件,OAT文件包含有两个特殊的段oatdata和oatexec。
oatdata包含有用来生成本地机器指令的dex文件内容。oatexec包含有生成的本地机器指令。它们之间的关系通过储存在oatdata段前面的oat头部描述。
在OAT文件的dynamic段,导出了三个符号oatdata、oatexec和oatlastword,它们的值就是用来界定oatdata段和oatexec段的起止位置的。
oat文件生成
APK在安装的过程中,会通过dex2oat工具生成一个OAT文件。
代码段来自文件frameworks/native/cmds/installd/commands.c
。
static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
const char* output_file_name, const char* dexopt_flags)
{
static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
execl(DEX2OAT_BIN, DEX2OAT_BIN,
zip_fd_arg, zip_location_arg,
oat_fd_arg, oat_location_arg,
(char*) NULL);
ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));