概念:可以被JVM识别加载并执行的文件格式。java,scala,kotlin,python,ruby都可以生成class文件
怎么生成class文件:
(1)通过我们的IDE ,build生成
(2)通过javac命令生成
怎么执行class文件
(1)通过IDE中的run执行
(2)通过java命令执行
class文件的作用:记录一个类文件的所有信息
class文件的结构:
类型 | 名称 | 数量 | 描述 |
---|---|---|---|
U4 | magic | 1 | 加密段 |
U2 | minor_version | 1 | 最小适配的jdk版本 |
U2 | major_version | 1 | 编译使用的jdk版本 |
U2 | constant_pool_count | 1 | 常量池的数量 |
cp_info | constant_pool | constant_pool_count-1 | 常量池的结构体,常量池 |
U2 | access_flags | 1 | 访问级别,作用域public,private … |
U2 | this_class | 1 | 当前类 |
U2 | super_class | 1 | 父类 |
U2 | interfaces_count | 1 | 类实现接口的数量 |
U2 | interfaces | interfaces_count | 当前类直接继承的接口,不包括父类的 |
U2 | fields_count | 1 | 类成员变量的数量 |
field_info | fields | fields_count | 成员变量 |
U2 | methods_count | 1 | 类方法的数量 |
method_info | methods | methods_count | 类方法的结构体,方法的名字类型等 |
U2 | attributes_count | 1 | 类属性的数量 |
attribute_info | attributes | attributes_count | 类属性的结构体,比如注解等 |
access_flags的取值范围
标志名 | 标志值 | 标志含义 | 针对的对象 |
---|---|---|---|
ACC_PUBLIC | 0X0001 | public类型 | 所有类型 |
ACC_FINAL | 0X0010 | final类型 | 类 |
ACC_SUPER | 0X0020 | 使用新的invokespecial语义 | 类和接口 |
ACC_INTERFACE | 0X0200 | 接口类型 | 接口 |
ACC_ABSTRACT | 0X0400 | 抽象类型 | 类和接口 |
ACC_SYNTHETIC | 0X1000 | 该类不由用户代码生成 | 左右类型 |
ACC_ANNOTATION | 0X2000 | 注解类型 | 注解 |
ACC_ENUM | 0X4000 | 枚举类型 | 枚举 |
constant_pool包含:
CONSTANT_Integer_info
CONSTANT_Long_info
CONSTANT_String_info
…
分别存储类中的int ,long ,String等类型的数据
CONSTANT_Class_info : 类相关信息 ,只保存索引
CONSTANT_Fieldref_info :成员变量相关信息,只保存索引
CONSTANT_Methodref_info:方法相关信息,只保存索引
下面来看一个class文件的内容,在android studio中
public class Hello { public static void main(String[] args){ System.out.print("hello"); } }
然后编译就能生成hello的class文件
位置在app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/cxt/hello
使用010Editor(可百度下载安装)打开hello.class文件
上图中我们就可以看到前面说的那些字段,点击就可以看到每个字段的信息,起始位置,长度大小等
class文件的弊端
内存占用大,不适合移动端
独占加载模式,加载速度慢
文件IO操作多,类查找慢
概念:dex是能够被DVM(Dalvik虚拟机 ART虚拟机)识别,并加载的文件格式
dex中包含了app的所有的源码
dex文件生成:
(1)IDE通过build生成
(2)通过dex命令生成
dex记录了整个工程中所有类文件的信息
结构:
文件头:head (文件头)
索引区:string_ids(字符串索引),type_ids(类型索引),proto_ids(方法原型索引),field_ids(域的索引),method_ids(方法的索引)
数据区:class_defs(类的定义区),data(数据区),link_data(链接数据区,so文件)
header部分
字段名称 | 偏移值 | 长度 | 说明 |
---|---|---|---|
magic | 0X0 | 8 | dex魔数字段固定信息“dex/n035/0” |
checksum | 0X8 | 4 | 校验码 |
signature | 0XC | 20 | sha-1签名 |
file_size | 0X20 | 4 | dex文件总长度 |
header_size | 0X24 | 4 | 文件头的长度 |
endian_tag | 0X28 | 4 | 标示字节顺序常量 |
link_size | 0X2C | 4 | 连接字段的大小,如果是0就是静态连接 |
link_off | 0X30 | 4 | 连接字段开始的位置 |
map_off | 0X34 | 4 | map数据基址 |
string_ids_size | 0X38 | 4 | 字符串列表中字符串的个数 |
string_ids_off | 0X3C | 4 | 字符串表基址 |
type_ids_size | 0X40 | 4 | 类列表里类型的个数 |
type_ids_off | 0X44 | 4 | 类列表基址 |
proto_ids_size | 0X48 | 4 | 原型列表中原型的个数 |
proto_ids_off | 0X4C | 4 | 原型列表的基址 |
field_ids_size | 0X50 | 4 | 字段个数 |
field_ids_off | 0X54 | 4 | 字段列表基址 |
method_ids_size | 0X58 | 4 | 方法个数 |
methon_ids_off | 0X5C | 4 | 方法列表基址 |
class_defs_size | 0X64 | 4 | 类定义标中类的个数 |
class_defs_off | 0X60 | 4 | 类定义列表基址 |
data_size | 0X68 | 4 | 数据段的大小 |
data_off | 0X6C | 4 | 数据段基址 |
索引区和数据区都可以通过010Edito0r查看到。还是上面那个Hello工程
dex文件位置:app/build/intermediates/dex/debug/mergeDexDebug/out
使用010Editor打开此文件下的classes.dex文件
上图就可以看到头部信息,索引区,数据区的信息。