class⽂件与dex⽂件解析
关于Android的热修复与插件化技术在如今基本上已经成为了“时髦技术”的标配了,或者说⽤来进⾏“炫技”的⼀种⽅式,毕境如今Android已经发展得⾮常之成熟了,基本上APP⽤的到东东都差不多,除了业务不同之外,但是!对于热修复与插件化并不是每个公司或者每个程序员愿意去应⽤到商⽤项⽬上的,因为既使不加它貌似对传统APP 的开发也⽊有啥影响,毕境加它还是有些繁锁的,⽽不管有没有在商⽤APP上去集成过它们,并不影响它被众多开发者所追捧,如今去⾯个试我想被问到热修复与插件化相关的技术问题应该只多不少,⽽且还得让你去对它底层的原理进⾏⼀些阐述,如果不需要⾯试也得有必要去掌握这⼀技术,因为毕境能集成到⾃⼰的APP上是能够实际解决APP的⼀些问题的,基于此有必要系统的去探究,彻底掌握它们,所以接下来会从基础开始⼀点点去揭开它神秘的⾯纱。
对于Dex⽂件是能够在Android被执⾏的⼀种格式,⽽它是由class⽂件进⾏演变过来的,在android的热修复中是需要涉及到Dex⽂件之间的⼀个diff操作的,⽽它的基础就是得对其⽂件结构有⼀定的了解,所以这⾥基础就先来熟悉⼀下⽂件结构。
class⽂件解析:
什么是class⽂件:
能够被JVM识别,加载并执⾏的⽂件格式。
如何⽣成⼀个class⽂件:
是不是只有java⽂件才能够⽣成class⽂件呢?其实不是的,看下⾯这张图就晓得了:
对于class⽂件的⽣成⼀般是由两种⽅式来完成的:IDE⾃动⽣成、javac命令,这⾥主要是演⽰⼀下javac命令的⽅式,对于它在我们学习j2se的时候已经经历过了,这⾥再来温故⼀下:
新建⼀个最简单的java⽂件,⾥⾯内容如下:
然后编译⽣成class字节码⽂件:
然后运⾏:
另外对于javac命令还可以指令编译的JDK版本,如下:
class⽂件的作⽤:
⽤⼀句话描述:“记录⼀个类⽂件的所有信息”,class⽂件的信息是远远多于java源代码的信息的,⽐如说我们在写java代码时并没有定义"this"、"super"关键字,但是确能够使⽤它们去调⽤当前类的⽅法或⽗类的⽅法,这是因为在⽣成class字节码⽂件的时候JVM帮我们记录了this和super关键字,所以从这点也能体会到class字节码⽂件的信息要远远多于Java源代码所看到的信息。
class⽂件格式详解:
⼀种8位字节的⼆进制⽂件。
这个⽐较好理解,跟⾳视频格式的⽂件类似。
各个数据按顺序紧密的排列,⽆间隙。
这个不像有些⽂件可能为了读取上的⽅便会做⼀些填充,⽐如每80个字节是⼀⾏,这样的好处就是能让class⽂件更加的⼩,能够更快的被JVM所加载。
每个类或接⼝都单独占据⼀个class⽂件。
以上是class⽂件从宏观⾓度去分析,下⾯具体来了解⼀下它的具体格式,各个字段代表的含义,如下为class⽂件的所有字段:
那你怎么知道上⾯就是class⽂件格式所有的字段呢?不要着急,等对其有⼀个基本了解之后会做实验来验证的,下⾯具体⼀个个⾃上⽽下来了解⼀下其字段的含义:magic:它其实是⼀个加密断,就像⽂件的MD5加密⼀样,⽤来判断其字节⽂件是否有被篡改过,如果被篡改过那么JVM会有⼀些处理的措施。
minor_version:表⽰此class⽂件最⼩能够被哪个版本的JDK所加载,也就是JDK最⼩适配的⼀个版本。
major_version:表⽰当前class⽂件由哪个版本的JDK所⽣成,⽐如咱们上⾯是由JDK1.8所⽣成的。
constant_pool_count:表⽰class⽂件中常量池的数量,通常来说是只有⼀个常量池,⾥⾯会存放许许多多的常量。
constant_pool:也就是真正存放常量的⼀个地⽅,其类型是⼀个结构体,如下:
access_flags:作⽤域标志,如class声明的pulic,private等。
this_class:这也就是为啥咱们可以直接在java源⽂件中使⽤"this"关键字的原因所在,jvm会⾃动⽣成⼀个这个字段。
super_class:其原理跟this_class⼀样。
interfaces_count/interfaces:保存了当前类实现的接⼝列表,interfaces_count 指的是当前类实现的接⼝数⽬,interfaces[] 是包含interfaces_count个接⼝的全局限定名的索引的数组,注意:只包含直接实现的接⼝,对于间接实现的不包含其中。
fields_count:表⽰类变量和实例变量的字段的数量总和。
fields:包含字段详细信息的列表,它是⼀个结构体类型:
methods_count:表⽰该类或者接⼝显⽰定义的⽅法的数量。
methods:包含⽅法信息的⼀个详细列表。也是⼀个结构体类型:
attribute_count/attributes:class⽂件的最后⼀部分是属性,它描述了该类或者接⼝所定义的⼀些属性信息。attributes_count指的是attributes列表中包含的attribute_info的数量。属性可以出现在class⽂件的很多地⽅,⽽不只是出现在attributes列表⾥。如果是attributes表⾥的属性,那么它就是对整个 class⽂件所对应的类或者接⼝的描述;如果出现在fileds的某⼀项⾥,那么它就是对该字段额外信息的描述;如果出现在methods的某⼀项⾥,那么它就是对该⽅法额外信息的描述。
以上的这些字段代表的class字节码⽂件的所有信息,其中对于access_flags包含的具体内容下⾯再做⼀个详解:
另外对于常量池constant_pool所包含的内容下⾯也来说明⼀下:
CONSTANT_Integer_info:存放着整型相关的常量。
CONSTANT_Long_info:存放着长整型相关的常量。
CONSTANT_String_info:存放着字符符相关的常量。
字符串常量池存的是实例还是引用?当然啦其它基本类型的也有对应的来表⽰,上⾯只列举常⽤的三个,另外下⾯还有⼏个稍复杂的字段类型:
CONSTANT_Class_info:包含着类常量相关的⼀些信息。
CONSTANT_Fieldref_info:包含类成员变量相关的⼀些信息。
CONSTANT_Methodref_info:包含⽅法引⽤相关的⼀些信息。
注意:以上三个其实都是存放的⼀些索引信息,最终内容还是指向到具体的CONSTANT_Integer_info、CONSTANT_Long_info、CONSTANT_String_info相关的具体类型当中。
说了这么多那class⽂件⾥⾯的结构确实如我们所描述的那样么?这⾥只要真实查看⼀个class⽂件的结构就就可以验证了么,所以下⾯来做⼀下这个实验:
咱们之前已经⽣成了⼀个class⽂件了,如下:
那接下来就以这个⽂件为例进⾏查看,那⽤什么软件可以查看到class⽂件的格式信息呢?这⾥需要介绍⼀款软件,如下:
软件名称:010 Editor
下载地址:
主要是⽤来分析⼆进制⽂件的,⽐如之后的dex⽂件的格式也需要通过它,安装好之后⽤它打开我们要分析的Hello.class⽂件,如下:
其中整个class⽂件是包裹在这个⼤的结构体中:
其中struct关键字很显然就是c语⾔中的结构体,然后展开它:
下⾯具体来看⼀下:
⽽其中可以看到u2_class_index和u2_name_and_type_index都是索引信息,其真正的数据就是在之前咱们说的那些CONSTANT_Integer_info、CONSTANT_Long_info、CONSTANT_String_info等相印的字段⾥,接着往下再看:
其它的常量池相关的信息基本都差不多,先忽略,接着就可以看到是如下信息:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。