AndroidClass⽂件格式及反编译原理
Java虚拟机(JVM)
对于JAVA程序来讲JVM就是⼀台计算机,和计算机⼀样它有处理器、内存、堆栈以及指令系统,Java程序在JVM上运⾏,它不需要考虑真实的物理计算机是什么平台,所以同⼀个Android APK可以在不同的硬件平台上运⾏。
Android虚拟机(Dalvik)
Dalvik虚拟机是Google专门为Android系统开发的,它是在apache的java虚拟机基础上针对移动设备做了专门的优化,允许在有限的内存中同时运⾏多个虚拟机的实例,降低每个实例对CPU和内存的资源占⽤,确保能够在CPU和内存相对有限的移动设备上也能适⽤。
ART
ART是在系统新增的⼀种应⽤运⾏模式,但是由于该模式相对于Dalivk会占⽤更⼤的存储空间,所以在4.4上默认是关闭的。⼀直到Android 5.0才默认开放。
Java 的跨平台特性决定了其可执⾏⽂件只能是与平台⽆关的字节码,⽽不是机器码。⽽Java虚拟机的主
要⼯作之⼀就是当应⽤在运⾏时,将平台⽆法识别的字节码翻译成机器码。 ART模式与Dalvik模式最⼤的不同在于,Dalvik模式是在应⽤运⾏时将字节码解释成机器码,⽽ART模式是在应⽤安装时就将字节码翻译成机器码,所以应⽤在运⾏时效率要⽐Dalvik⾼。另外ART是基于寄存器的⽽Dalvik基于堆栈,和Dalvik相⽐没有了堆栈操作。
Android 应⽤开发涉及到的⼏个⽂件
1. Java⽂件
应⽤程序源代码⽂件。
1. Class⽂件
Java源码编译⽣成的⽬标⽂件,相当于C代码编译出来的.o⽂件。Java语⾔为了实现跨平台的⽬的,所以定义了⼀套与操作系统和硬件平台⽆关的字节码
格式,class⽂件⾥⾯记录的就是Java源码编译后的字节码⽂件。
1. Dex⽂件
Android平台上的可执⾏⽂件,相当于windows平台上的.exe⽂件,该⽂件专门为在Android Dalvik虚拟机上运⾏⽽设计的,它将多个class字节码⽂件按照固定的格式整合优化成⼀个dex字节码⽂件。
1. APK⽂件
Android应⽤的安装⽂件,它是由dex可执⾏⽂件以及资源⽂件如图⽚、布局等⽂件打包⽽成。
Class字节码⽂件分析
⽂件结构:
类型名称数量
u4magic1
u2minor_version1
java源代码加密
u2major_version1
u2constant_pool_count1
cp_info constant_pool constant_pool_count - 1
u2access_flags1
u2this_class1
u2super_class1
u2interfaces_count1
u2interfaces interfaces_count
u2fields_count1
field_info fields fields_count
u2methods_count1
method_info methods methods_count
u2attribute_count1
attribute_info attributes attributes_count
1. Magic:
class⽂件的魔数,class⽂件的魔数是⼀个固定的值:0XCAFEBABE
1. minor_version  major_version:
⽂件版本号,对应JDK版本。
1. constant_pool_count和constant_pool:
常量池数和常量,常量池中记录了java⽂件中的所有的常量类型包括字符串、类名、⽅法名等,除了JAVA源代码中定义的的常量,常量池中还包含下⾯⼏种类型:
1. 类和接⼝的全限定名
2. 字段的名称和描述符
3. ⽅法的名称和描述符
除此之外常量池还描述了类的引⽤信息。
总共有如下12种类型:
⼊⼝类型标志值描述
CONSTANT_Utf81JAVA源码中的各种字符串,字符串常量,类的全限定名,字段、⽅法的描述符,引⽤的字段和⽅法的描述符等
CONSTANT_Integer3int类型字⾯值
CONSTANT_Float4float类型字⾯值
CONSTANT_Long5long类型字⾯值
CONSTANT_Double6double类型字⾯值
CONSTANT_Class7对⼀个类或接⼝的符号引⽤CONSTANT_String8String类型字⾯值
CONSTANT_Fieldref9对⼀个字段的符号引⽤CONSTANT_Methodref10对⼀个类中声明的⽅法的符号引⽤CONSTANT_InterfaceMethodref11对⼀个接⼝中声明的⽅法的符号引⽤CONSTANT_NameAndType12对⼀个字段或⽅法的部分符号引⽤CONSTANT_MethodHandle15表⽰⽅法句柄
CONSTANT_MethodType16标志⽅法类型
CONSTANT_InvokeDynamic18表⽰⼀个动态⽅法调⽤点
每种常量类型结构表
常量字节项类型描述
CONSTANT_Utf8tag u11 length u2
bytes u1
CONSTANT_Integer
tag u13
bytes u4
CONSTANT_Float
tag u14
bytes u4
CONSTANT_Long
tag u15
bytes u8
CONSTANT_Double tag u16
bytes u8
CONSTANT_Class
tag u17
index u2
CONSTANT_String
tag u18
index u2
CONSTANT_Fieldref tag u19
index u2指向CONSTANT_Class的索引值
index u2
指向CONSTANT_NameAndType的索引
CONSTANT_Methodref tag u110
index u2指向CONSTANT_Class的索引值index u2指向CONSTANT_Class的索引值
CONSTANT_InterfaceMethodref tag u111
index u2指向CONSTANT_Class的索引值index u2指向CONSTANT_Class的索引值
CONSTANT_NameAndType tag u112
index u2指向该字段或⽅法名称常量的索引值index u2指向该字段或⽅法描述符常量的索引值
CONSTANT_MethodHandle tag u115
reference_kind u1值必须1~9,它决定了⽅法句柄的的类型reference_index u2对常量池的索引
CONSTANT_MethodType
tag u116
index u2对常量池中⽅法描述符的索引
CONSTANT_InvokeDynamic tag u118
index u2对引导⽅法表的索引
index u2
指向CONSTANT_NameAndType的索引
1. Access_flags
它定义了java源⽂件中类或者接⼝的类型
标志名值含义设置者ACC_PUBLIC0x0001public类型类和接⼝ACC_FINAL0x0010类为final类型类
ACC_SUPER0x0020使⽤新型的invokespecial语义类和接⼝
ACC_INTERFACE0x0200接⼝类型,不是类类型接⼝
ACC_ABSTRACT0x0400abstract类型接⼝和部分类
1. this_class
对常量池的索引。在this_class位置的常量池⼊⼝必须为CONSTANT_Class表,该表索引指向⼀个CONSTANT_Utf8,该CONSTANT_Utf8存放该类的全限定名。
1. super_class
对常量池索引,在super_class位置的常量池⼊⼝是⼀个指向该类超类全限定名的CONSTANT_Class⼊⼝,如果该类直接继承⾃object 类,那索引值为0.
1. interfaces_count和interfaces
由该类⾃⼰实现的或者该类继承后扩展的接⼝。
APK安全
根据上⾯介绍的Class⽂件格式可以看到,Class⽂件完整描述了Java源码中的所有信息,所以根据固定的class⽂件格式,可以反编译出java源码。
我们⽤⼀个简单的java源⽂件举例:
原始的源码⽂件helloworld.java如下:
编译⽣成的helloworld.class如下:

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