前期预备知识
dex/class
- class文件结构解析
-
什么是class文件?
能够被jvm识别,加载并执行的文件格式
-
如何生成一个class文件
- [x] 通过IDE自动帮我们build
- [x] 手动通过javac 去生成class文件
PS: 如何制定jdk版本生成字节码文件呢?—>javac -target 1.6 -source 1.6 HelloWorld.java - [x] 通过java命令去执行class文件
java com.example.hostfit.Test ps: 执行时根据全类名来执行的
-
class文件的作用 记录类文件的所有信息(记录了this super 等关键字)
-
- 一种八位字节的二进制流文件
- 各个数据按照顺序紧密排列,无间隙
- 每个类或接口都单独占一个class文件
-
class文件弊端
- 内存占用大,不适合移动端
- 堆栈加载模式,加载速度慢
- 文件IO操作多,类查找慢
-
- dex文件结构解析
-
什么是dex文件
被DVM虚拟机识别,加载并执行的文件格式
-
如何生成dex文件
- [x] 通过IDE自动帮我们build生成
- [x] 手动通过dx命令去生成dex文件
javac -target 1.6 -source 1.6 Test.java
生成class文件。ps:指定1.6 版本为了保证兼容dx --dex --output=Test.dex com/example/hostfit/Test.class
ps: 是根据全类名来找的
- [x] 手动运行dex文件在手机上
- 将dex文件push 到手机存储卡中
adb push Test.dex '手机路径(例如:/sdcard)'
dalvikvm -cp Test.dex com.example.hostfit.Test
ps: 注意全类名
- 将dex文件push 到手机存储卡中
-
dex文件的作用
记录整个工程中所有类文件的信息。
-
- 一种八位字节的二进制流文件
- 各个数据按照顺序紧密排列,无间隙
- 整个应用中所有的java源文件都放在一个dex文件中 ps: 不考虑android 官方提供的multidex
-
- class 与 dex 文件对比
- 本质上他们都是一样的,dex文件从class文件演变而来
- class文件存在许多冗余信息(一个类就有一个常量池),而dex文件会去除冗余,并进行整合
jvm/dvm/art 三种虚拟机
-
java 虚拟机结构解析
- jvm整体结构
-
java代码的编译和执行过程
-
Java 内存管理
-
Java 栈区
用来存放Java方法执行的所有数据 ps: method call-> a -> b - c;栈区由栈帧组成,一个栈帧代表一个方法的执行。
那什么是栈帧呢?每一个方法从调用到执行完成就对应一个栈帧在虚拟机中入栈到出栈。每一个栈帧包括局部变量表、栈操作数、动态链接、方法出口。例如(StackOverFlow异常)
本地方法栈:和Java方法栈如出一辙,只不过本地方法栈是专门为Native方法服务的
-
方法区
存储被虚拟机加载的类信息,常量,静态变量,即是编译器后等数据,用于占据内存的
-
Java堆
所有通过New创建的对象的内存都在堆中分配,是虚拟机中最大的一块内存,是GC 要回收的部分
- Young Generation : 刚刚New出来的对象
- Old Generation: 当Young Generation 中内存空间不足的时候,就会将Young Generation 中的对象按照一定的算法、规则等存放到Old Generation, 这样 Young Generation 就可以继续分配内存,当两者都没有剩余的空间的时候,就会发生OOM异常,垃圾回收器主要针对这两块内存区域,
- Permanent Generation: Java8 已经移除
特点:Young Old Generation 可以动态分配,当我们的服务器处理的是及时通讯相关服务,就可以将Young Generation内存区域调整大一些;当我们不需要频繁去创建对象的时候,可以将Young Generation 内存区域调整小一些,这样达到内存对象常驻的效果
-
-
Java 内存回收机制
-
Dalvik 与 jvm的不同
- 执行的文件不同 一个是dex 一个是class文件
- 类加载的系统(ClassLoader)与JVM的区别比较大
- jvm 只能同时存在一个,DVM可以同时存在多个
- DVM 是基于寄存器的(运行更快),JVM 是基于栈的
-
ART比Dalvik有哪些优势
- DVM 使用的是JIT来将字节码转换成机器码(每次运行),效率低
- ART 是采用AOT的预编译技术(安装的时候就将字节码转换成机器码存储于介质中,不需要每次进行转换),执行速度更快
- ART 会占用更多的应用安装时间和存储空间(以空间换时间)
class loader(Java Android)
类是如何加载到虚拟机的?
-
Java 中的ClassLoader回顾
-
Android中ClassLoader 作用详解
-
Android ClassLoader的种类
-
BootsClassLoader
用来加载Android framework层的一些dex文件
-
PathClassLoader
用来加载已经安装到系统中的apk文件中的dex文件
-
DexClassLoader
用来加载指定目录中dex文件
-
BaseDexClassLoader
是PathClassLoader DexClassLoader 的父类
一个App至少需要BootClassLoader 和PathClassLoader
-
-
Android ClassLoader 的特点
-
双亲代理模型特点
当前的classLoader去加载此类,如果当前此类已经被ClassLoader加载过就不再加载,直接返回; 如果未加载,便会查询它的Parents 是否加载过此类,如果加载过 就返回parents加载过的字节码文件; 如果整个继承线的都没有加载过此类,便会子类真正的加载,提高类加载效率。这样就会带来以下两个作用
-
类加载的共享功能 一些FrameWork层级的类 ,一旦被顶层的classLoader加载过,那么它就会缓存到内存里面,以后任何地方用到,就不用重新加载了
-
类加载的隔离功能 不同继承路线上的ClassLoader 加载的类不是同一个类,避免开发者自己写一代码伪造成系统的类库来访问我们系统可见成员变量。例如:系统层级的类一般初始化的时候就会加载,比如java.lang.String, 应用程序启动之前就会被系统加载,如果在一个app里面写一个自定String 替换掉java.lang.String 会造成严重的安全问题。判断是否是同一个类判断,除了className packageName 另外还需要是同一个ClassLoader加载的。
-
-
ClassLoader 源码 (加载流程)
ClassLoader loadClass 首先判断被自己或者双亲加载过,如果未加载过,调用BaseDexClassLoader 的findClass,调用DexPathList findClass ,并且完成将dex文件转换成DexFile ,转换成Elements, 遍历数据,调用DexFile loadClassBinaryName - > native
-
-
Android 中动态加载要点?
- 有许多组件(Activity)类需要注册才能使用
- 资源动态加载复杂(注册、兼容性)
- 程序运行的时候需要一个上下文环境