ART深入浅出4--了解Dex文件格式(1)

ART虚拟机 | Dex Verify实现详解 Dex Verify是Android 系统对Dex文件进行合法性与安全性校验的核心流程。在介绍Dex Verify实现原理之前,先介绍下Dex文件,便于理解Verify实现原理。将多个.class字节码文件编译合成一个.dex字节码文件。Dex指令:Dex指令是Android虚拟机执行的底层操作码,通过寄存器架构直接操作数据和控制逻辑。每条指令由opcode和操作数组成。如,常见的opcode如const、move、invoke等,const/4表示将立即数存入寄存器。 阅读详情

本文基于Android 7.1,不过因为从BSP拿到的版本略有区别,所以本文提到的源码未必与读者找到的源码完全一致。本文在提供源码片断时,将按照 <源码相对android工程的路径>:<行号> <类名> <函数名> 的方式,如果行号对不上,请参考类名和函数名来找到对应的源码。

可以参考我之前写过的文章:http://blog.youkuaiyun.com/doon/article/details/51691627

理解dex文件的基本格式

理解dex指令特点

要理解dex文件,首先要dex的指令特点。dex被称为是基于寄存器的虚拟机指令。这里的寄存器,不是指物理寄存器,而是指虚拟机虚拟出的寄存器。而且不同于有我们熟悉的编译性语言(如C/C++),dex指令在运行时,只需要寄存器,不需要堆栈。dex指令有如下特点:

  1. 一个函数拥有一组独立的寄存器 将每个函数的寄存器数量是不固定的,标记为V0~Vn-1,最多可以有65535个
  2. 一个函数的虚拟寄存器可以划分为三部分:
    1. 自变量区:保存的是函数内部用到的自变量
    2. 参数输入区:保存的是输入的参数值
    3. 输出参数区:被用于保存被调用函数的参数。因为输出参数区只用作参数输出,所以在虚拟机实现的时候,通常把调用函数的输出参数区与被调用函数的输入参数区重叠。
  3. 假设一个函数有M个参数,那么参数将占据 Vn-m ~ Vn-1,剩余部分将被内部变量占据
  4. 假如一个函数有自变量a,b,且a,b的作用域不重叠,那么它们可以占据同一个寄存器Vi

如下图:
Dex寄存器图

字符串池

字符串在java和dex中都是非常重要的。不仅在编程中包含大量的常量字符,而且,java的类名、方法名、成员名等都是以字符串的形式保存下来的。
那么,字符串在dex中如何存储呢?了解java class文件结构的朋友一定也听说过,在class文件中有一个字符串池,保存了源码中存在的各种字符串以及各种名称。同样的,在dex文件中,也可以看到这样的字符串池.
dex文件相对于class文件的优越在于,dex文件将多个class集中在一起,消除了它们之间的重复字符串。

dex文件对字符串的引用,是通过stringId来实现的。它的定义是
art/runtime/dex_file.h:163 DexFile

  // Raw string_id_item.
  struct StringId {
    uint32_t string_data_off_;  // offset in bytes from the base address

   private:
    DISALLOW_COPY_AND_ASSIGN(StringId);
  };    

string_data_off_相对于的base address是去掉了dex header后的地址。
这样就可以直接拿到一个字符串了。

Dex文件中的各种表

当一条指令需要引用一个类、字符串、一个对象/类的方法、一个对象/对象的成员的时候,它必须通过索引来实现。比如,有一条指令:
new-instance v0, type@120
它表示,创建一个类,这个类被标记在typeIds表的120位置处,并将结果放到v0寄存器内。
类似的指令包括invoke-virtual/static/super/interface, iput/iget, sput/sget等指令const-string, const-class等指令,它们都需要访问一个表索引。
在dex文件中,共有下面几种表:
stringIds: 字符串池,这个表内包含的StringId类型的数据,这是字符串池索引,所以访问字符串的地方,只需要给出一个字符串索引即可。
TypeIds: 类型索引数组。包含的是类、枚举、接口的类型。对应的数据结构是TypeId
FieldIds: 所有被引用的域的数组列表。不仅是在本dex文件内定义的class,也包括在外部dex文件中定义,但是被本文件内代码使用的成员类型。这里只是定义了Field的信息;
MethodIds: 同FieldIds,都是定义被应用函数的列表。这里并没有函数的实现代码。
ProtoIds: 定义了所有函数的参数原型列表。这里定义了被应用的函数以及用户定义的函数的参数列表信息

TypeId

它的定义
art/runtime/dex_file.h:171 DexFile

  // Raw type_id_item.
  struct TypeId {                                                                                                                    
    uint32_t descriptor_idx_;  // index into string_ids

   private:
    DISALLOW_COPY_AND_ASSIGN(TypeId);
  };

字符串的偏移是stringIds[descriptor_idx_]。需要指出的是,这里的类名字符串不是我们在java中常用的 java.lang.Object形式,而是java/lang/Object这样的形式。

需要注意的是,descriptor_idx_虽然是32位,但是实际上只有16位可用。因为stringIds最大值是16。把它定义成32位,只是为了对齐。

FieldId

art/runtime/dex_file.h:178

  // Raw field_id_item.                                                                                                              
  struct FieldId {
    uint16_t class_idx_;  // index into type_ids_ array for defining class
    uint16_t type_idx_;  // index into type_ids_ array for field type
    uint32_t name_idx_;  // index into string_ids_ array for field name

   private:
    DISALLOW_COPY_AND_ASSIGN(FieldId);
  };

class_idx指出该field所属的类,type_idx指出field的类型所在的索引,name_idx指出的名字索引。
如果你仔细观察,会发现,FieldId中并没有包含field的访问域(public/protectd/private/protected)和是否是静态、是否是fianl等信息。因为这个FieldId只是告诉代码去那里查询这个field,所以就不包含其他信息了。(其实,只需要class_idx和name_idx就足够了)

  // Raw proto_id_item.
  struct ProtoId {                                                                                                                   
    uint32_t shorty_idx_;  // index into string_ids array for shorty descriptor
    uint16_t return_type_idx_;  // index into type_ids array for return type
    uint16_t pad_;             // padding = 0
    uint32_t parameters_off_;  // file offset to type_list for parameter types

   private:
    DISALLOW_COPY_AND_ASSIGN(ProtoId);
  };

shorty_idx_: 这是参数表的简写
return_type_idx: 指出返回值的索引类型
paramters_off_: 参数列表数据的偏移。
首先要说明的是shroty_idx。
我们知道,java的jni有一套方法签名:

Java类型签名
booleanZ
byteB
charC
shortS
intI
longL
floatF
double D
类L全限定名;,比如String, 其签名为Ljava/lang/util/String;
数组[类型签名, 比如 [B

比如 函数Object foo(int[], long, double, String) 就会写成 “([IJDLjava/lang/String;)Ljava/lang/Object;”。
在如果将其中的类型限定符去除,只用一个字母表示参数的类型和返回值,那么就变成这样了: “L[JDL” 。其中第一个字母”L”表示返回值为一个对象,从第二个字母开始,都是参数。这就是短格式。

parameters_off_索引指出了参数类比,他是 TypeList以及TypeList的子格式TypeItem,它们的格式:
art/runtime/dex_file.h:245

  // Raw type_item.
  struct TypeItem {                                                                                                                  
    uint16_t type_idx_;  // index into type_ids section

   private:
    DISALLOW_COPY_AND_ASSIGN(TypeItem);
  };

  // Raw type_list.
  class TypeList {
   public:
   ....
   private:
    uint32_t size_;  // size of the list, in entries
    TypeItem list_[1];  // elements of the list
    DISALLOW_COPY_AND_ASSIGN(TypeList);
  };

TypeList是一个带头部大小的可变数组,数组的成员是TypeItem,而TypeItem的类型是type_idx_,即typeIds的索引。
这样,typeList就定义了一个参数列表。

好了,dex文件先介绍到这里,下节我们将重点介绍ClassDef的相关内容。

Android运行时文件格式解析:DEX、ODEX、OAT、VDEX与ART Android应用的运行依赖于多种特殊的二进制文件格式,其中DEX文件作为基础字节码容器,包含了Java/Kotlin代码编译后的Dalvik指令集。随着ART运行时的引入,Android采用了AOT编译技术,将字节码转换为本地机器码,显著提升了执行效率。这一过程生成了OAT文件(ELF格式的本地代码容器)和优化后的ODEX文件。在Android 8.0及更高版本中,系统进一步引入了VDEX文件来分离验证信息,优化应用更新流程。理解这些文件格式的工作原理对于性能优化、存储空间管理和兼容性处理都至关重要,特别 阅读详情

相关推荐

ART深入浅出(7) - OAT文件的格式

本文基于Android 7.1,不过因为从BSP拿到的版本略有区别,所以本文提到的源码未必与读者找到的源码完全一致。本文在提供源码片断时,将按照 : 的方式,如果行号对不上,请参考类名和函数名来找到对应的源码。 从本章开始,我将介绍OAT文件的格式 以ELF文件格式作为外壳 从手机上下载一个oat文件。一般我都是研究boot.oat。比如,用命令 adb pull /data/da

doon的专栏 4086

Android Tinker Dex差分与合成原理的源码深度剖析(3)

Android应用的Java代码在编译后会转换为Dex(Dalvik Executable)格式,这种格式专为移动设备优化,减少了冗余信息并提高了类加载速度。一个典型的Dex文件包含以下核心结构:

Android开发领域创作者 1126

一篇文章让你清楚DVM、JVM、ART、JIT、ODEX、VDEX、DEX、oat

DVM 和 JVM的区别 1、DVM基于寄存器,JVM基于栈。 DVM效率要更高 解释为什么寄存器效率更高? a、 因为寄存器是CPU中的一部分, 堆栈是内存的一种结构。 内存是CPU和硬盘之间的通道。 寄存器是CPU的储存器,速度快。 b、 一个是直接对CPU进行操作,一个是对内存操作,然后在转化成CPU指令操作。所以寄存器效率更...

weixin_39079048的博客 2558

dex文件格式笔记

Dex是Dalvik Executable的简称 Dex文件包含了编译java生成的.class文件,由dx工具将java字节码转化为smali字节码 apk安装后,对于dalvik第一次运行系统完成dex优化,转化为odex文件,存放在/data/dalvik-cache目录下,执行时加载odex文件到内存,art虚拟机是转成oat文件,都是在前后加些 odex优化仅在dex文件之上添加头和数据...

kernweak的博客 538

[零基础]用docker搭建Hadoop集群

[零基础]用docker搭建Hadoop集群,每一步都有详细的解释!

weixin_56114243的博客 2万+

机器学习笔记之玻尔兹曼机(一)基本介绍

在受限玻尔兹曼机——模型表示(Representation)一节中以玻尔兹曼机为引,介绍了受限玻尔兹曼机。从本节开始,将正式介绍玻尔兹曼机。相比于它的表示和推断过程,我们更关注它在求解过程中出现的问题。

静静的学习就好 7924

dex文件解析(第三篇)

一张图搞懂dex 大图这里 图1 dex 当然也可以通过下面的图12 DexFile的文件格式,了解更清楚。 DEX文件详解 什么是dex文件?如何生成一个dex文件dex文件的作用dex文件格式详解 什么是dex文件? dex文件是Android系统中的一种文件,是一种特殊的数据格式,和APK、jar 等格式文件类似。 能够被DVM识别,加载并执行的文件格式。 简单说就

键盘的起始页 2万+

Qt绘图实战:用QGraphicsItem实现可拖拽箭头连接(附完整代码)

本文详细介绍了如何使用Qt的QGraphicsItem框架实现一个功能完备的可拖拽箭头连接组件。通过核心代码示例,讲解了如何创建自定义图形项、实现智能吸附、碰撞检测以及实时拖拽编辑路径,为构建流程图、拓扑图等专业图形编辑器提供了完整的解决方案。

m2n3b4v5c6的博客 625

ART深入浅出6--了解Dex文件格式(3)

hander_off_ 是 hander结构的偏移,这个偏移是从codeItem.insns_ + sizeof(TryItem ) * codeItem.tries_size_ 开始的。finally块是放在最后的,而且finally只有address_值,没有type_idx_的值。ins_size_是指令的大小,单位是2字节。handler结构是一个不定长的结构,在TryItem数组之后有一个handler_size的leb128编码的数据,表示handler的结构。ins_size_是参数的个数。

zhangmiaoping23的专栏 769

程序自动化填写网页表单数据

如何让程序自动化填写网页表单数据,特别是涉及到批量数据情况时,可以减少人力。下面是涉及到的一些场景,都可以通过相关自动化程序实现。

Y 2424

银河麒麟V10系统grub崩溃急救指南:从光盘救援到完整恢复(附常见错误排查)

本文详细介绍了银河麒麟V10系统grub崩溃的急救方法,从使用安装光盘进入救援环境到完整恢复系统的全流程。针对不同损坏程度(轻度、中度、严重)提供了分级恢复策略,包括grub2-install和grub2-mkconfig等关键命令的使用,并附有常见错误排查表,帮助用户快速解决引导问题。

weixin_30955617的博客 483

2020-10-27(dex文件解析)

一张图搞懂dex 大图这里 当然也可以通过下面的图12 DexFile的文件格式,了解更清楚。 DEX文件详解 什么是dex文件? 如何生成一个dex文件 dex文件的作用 dex文件格式详解 什么是dex文件? dex文件是Android系统中的一种文件,是一种特殊的数据格式,和APK、jar 等格式文件类似。 能够被DVM识别,加载并执行的文件格式。 简单说就是优化后的android版.exe。每个apk安装包里都有。包含应用程序的全部操作指令以及运行时数据。 相对于PC上的java虚拟机能运行.cl

寻梦&之璐 7602

Abaqus 2023 保姆级安装避坑指南:从环境变量到许可证配置,一次搞定

本文提供Abaqus 2023的详细安装指南,涵盖环境变量设置、许可证配置等关键步骤,帮助用户避开常见安装陷阱。通过系统环境检查、目录结构规划、许可证服务器安装及Java环境配置等实用技巧,确保顺利完成安装并优化软件性能。

weixin_42524276的博客 425

ART深入浅出3--了解Boot.art和boot-*.art

在Android7.0之前,所有bootclasspath指定的库会被同一编译成为boot.oat和boot.art两个文件。其中boot.oat包含了编译后的机器码指令,而boot.art文件,则是一个类对象映像。boot.art内包含了所有framework/base/preloaded-classes文件列出的所有类。这些类会被一次性的载入到内存中,并可以被直接使用。

doon的专栏 9034

零倾覆力矩点(ZMP)

从形式上讲,ZMP 指的是空间中相对于一个平面(通常是地平面)抵消接触力矩的点的集合。这个集合实际上是一个轴,而不是一个点,但为了方便起见,让我们按照传统的推导方法来计算地面平面上的 ZMP。这一推导从任何多刚体系统的牛顿-欧拉运动方程开始:其中,为机器人的总质量,为重力矢量,为系统的重心,为加速度,为固定点的角动量变化率。在右侧,表示净接触扭矩,即施加到机器人上的所有接触扭矩之和,坐标取自质心 (COM)。

机器人控制与仿真应用 2371

【项目实战】SOVD协议(面向服务的车辆诊断协议)

此外,AUTOSAR组织将SOVD部分内容的软件实现定义在了R22-11及以上版本的AUTOSAR Adaptive规范中,还支持动态发现车内诊断功能、获取高性能计算机(HPC)的Log信息等新的诊断需求,更符合当前软件定义汽车概念下的行业趋势。而SOVDGateway作为边缘节点,也肩负着对SOVD Client进行认证以及权限控制的责任,从而保证车辆的信息安全。相较于传统的UDS(Unified Diagnostic Services)协议,SOVD不仅保留了传统的读写数据、例程控制、故障读取等功能,

奶爸的编程之路,也就一周冷个三天 1903

Android[art]-Android dex,odex,oat,vdex,art文件结构学习总结

参考学习博客: Android Dex文件格式(一):https://blog.youkuaiyun.com/p312011150/article/details/80501690 dex文件解析(第三篇) :https://blog.youkuaiyun.com/tabactivity/article/details/78950379 Android安全–Dex文件格式详解:https://www.cnblogs.co...

TaylorPotter的博客 9952

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

ART深入浅出5--了解Dex文件格式(2)

本节介绍ClassDef的格式。ClassDef是Dex文件内部表示一个类的结构。包含了类的基本数据,如类的名称,访问级别,Field列表,Method列表等信息。

doon的专栏 1678

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

android oat如何提取dex文件字节码,ART、OAT格式介绍与dex文件提取

dex文件经过dex2oat编译,会生成.art、.oat两个文件,oat是一个android定制的elf文件,原始dex也保存在其中。8.0后,dex单独保存到.vdex文件中。art文件类似于一个内存映像,缓存常用的ArtField、ArtMethod、DexCache等内容,加载后可直接使用,避免解析耗时。art文件格式介绍以boot.art为例,它分为Image Section和Bitma...

weixin_32926649的博客 1379

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android dex、odex、oat、vdex、art区别

1.dex java程序编译成class后,dx工具将所有class文件合成一个dex文件,dex文件是jar文件大小的50%左右. 2.odex(Android5.0之前)全称:Optimized DEX;即优化过的DEX. Android5.0之前APP在安装时会进行验证和优化,为了校验代码合法性及优化代码执行速度,验证和优化后,会 产生ODEX文件,运行Apk的时候,直接加载ODEX,避...

Android系统攻城狮 8123

Android Dex文件详解

前言 相信大家都熟悉dex文件,把一个apk给解压缩,就会得到一堆dex文件,但是这些dex文件是怎么来的,又有什么用,为什么这样设计,有进行思考过吗 俗话说知其然,知其所以然,本篇文章开始探究一下这些底层实现细节。 正文 不同的虚拟机 JVM JVM是Java Virtual Machine的简称,即Java虚拟机,它本质是一层软件抽象,在这之上才可以运行Java程序。Java文件经过编译后会生成JVM字节码,和C语言编译后生成的汇编语言不同,C编译成的汇编语言可以直接在硬件上跑,但是Java编译生成的字

Misdirection_XG的博客 8283

Java虚拟机ART 读书笔记 第3章 深入理解Dex文件格式

Java平台上,字节序采用的是Big Endian,class文件也是,而Android平台上的Dex文件默认的字节序是Little Endian(这可能是因为ARM CPU(也包括X86CPU)采用的也是Little endian字节序的原因吧)。参数组合的格式也有要求,不同的字符代表不同的参数,参数的比特位长度又是由字符的个数决定。比如:A表示一个占4比特的参数,AA代表一个占8比特的参数,AAAA代表一个16比特长的参数。比如øø表示这样一个参数,这个参数长度为8位,每位的取值都是0。

Godam 1089

关于Dalvik、ART、DEX、ODEX、JIT、AOT、OAT

关于Dalvik、ART、DEX、ODEX、JIT、AOT、OAT 发表于 2017-06-30 | 分类于 Android | | 字数统计 | 阅读时长 关于Dalvik、ART、DEX、ODEX、JIT、AOT、OAT,说真的,我看着都头大,每次看完过不了多久就会忘记一些内容,然后再去搜资料,好记性不如烂笔头,写在这里随时温故。 Dalvik&ART 1.1 Dalvik D...

Strange_Monkey的博客 3553

Android .dex、.odex、Dalvik、ART、AOT、OAT

文章来源:https://www.jianshu.com/p/e52b7e460748 https://zhuanlan.zhihu.com/p/53723652 目的 理清 .dex、.odex、ART、AOT、OAT 等近似名称的概念和意义。 APK 生成 最终 apk 内的代码文件为 .dex 文件。 APK 安装运行 基础概念 **AOT:**编译方式,运行前编译。AOT是指"Ahead Of Time",与"Just In Time"不同,从字面来看是说提前编译。JIT是运行时编译,是动态编译,

u013750244的博客 2249

android studio 输出apk过程,apk中的文件格式(bsh文件,dex文件),JVM、DVM、ART的区别,IOS与安卓的区别,ART和Dalvik

目录 android studio 输出apk过程 bsh文件: dex文件: Android 知识:JVM、DVM、ART的区别: ART虚拟机 将apk文件使用360加压边可以看到Android studio 打包后输出的apk内在文件 IOS与安卓的区别: android studio 输出apk过程 1.通过aapt打包res资源文件,生成R.java、res...

ZhangJiqun&191cm&85kg 2242
上一篇: ART深入浅出3--了解Boot.art和boot-*.art
下一篇: ART深入浅出5--了解Dex文件格式(2)
漂流的代码
博客等级 码龄23年 188粉丝 99原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值