JVM 整体结构
垃圾回收,通常称为 GC 。
类加载器:
箭头指向的就是对应类加载器需要加载的 文件。
前两个类加载器 加载的是我们 jdk 中特定路径下的 jar 包
第三个加载的是应用程序中的 类
可以自定义的 ClassLoader
类加载器 指的就是 ClassLoader ,class 被 ClassLoader 加载后就会存储到内存空间中,内存空间又被分为 方法区,Java 堆,java栈,方法本地栈。这四个区域用来存储 class 不同的部分。
Java 代码的编译和类加载的过程
编译流程:源代码 —— 词法分析器 —— Token 流 —— 语法分析器 —— 语法树/抽象语法树 —— 语义分析器 —— 注解抽象语法树 —— 字节码生成器 —— JVM 字节码
类加载过程
加载:获取class字节码文件并且载入到 JVM 内存里
验证:检查读入的字节流是否符合 JVM 规范的描述,不会造成安全错误
准备:主要是为类变量(注意:不是实例变量)分配内存,并且赋予初值
分析:把类的常量池中所有的符号引用改为直接引用
初始化:执行静态初始化程序,把静态变量初始化成指定值,如果有静态代码块,则也会执行。
内存管理和垃圾回收
java 将内存区域分为了四个区域,方法区,栈区,堆区,本地方法栈
java 栈区
他作用是用来存放java 方法执行时的所有数据,栈区就是用来描述 java 方法执行的完整内存模型。 组成:由栈帧组成,一个栈帧代表一个方法的执行,每个方法从调用到执行完的过程就对应一个栈帧在虚拟机中入栈到出栈。例如:从 在 a 方法中调用 b 方法,a 方法的栈帧首先入栈,然后执行到调用 b 方法的代码时会创建一个 b 方法的栈帧入栈,然后执行 b 方法,b 方法执行完后随即对应的栈帧出栈,就会回到 a 调用 b 方法的地方,然后 a 继续执行,执行完后 a 方法的栈帧会被从java栈区弹出。栈帧中包含的内容:局部变量表,栈操作数,动态链接,方法出口。
本地方法栈
作用:本地方法栈是专门为 native 方法服务的 ,和 java 栈区差不多
方法区
存储被虚拟机加载的类信息,常量,静态变量 等一系列编译期所要保存的数据,方法区是永远占据内存的。
堆区
作用:所有通过 new 创建的对象的内存都是在堆中进行分配
特点:是虚拟机中最大的一块内存,是 GC 要回收的部分
堆区内存:
垃圾收集
垃圾收集算法:
引用计数法,对象被引用后 计数器+1,取消引用后 -1,当计数器 为0 ,则对象为 0 后 为垃圾对象。缺陷:如 对象 A ,B ,A 引用了 B ,B 引用了 A ,此时没有别的引用 A B ,则这两个已经是垃圾了。但是不能够被回收。
可达性算法,也叫做根搜索算法,从 GC Root 节点开始算起,从这个节点开始寻找所有的引用节点,找到这个节点以后继续寻找这个节点的引用,当所有的节点找到后,剩余的节点则就是没有被引用的节点。这些就是不可达的节点,jvm 就会认为这些是垃圾对象。下面根据图来看一下:
如 objD 和 objE 没有可达的路径,所以会被回收
引用类型
强引用,弱引用,软引用,虚引用
下面看一下弱引用创建方式:
//强引用 Object obj = new Object(); //弱引用 WeakReference<Object> weak = new WeakReference<>(obj); //ob 指向 null obj = null; weak.get(); //获取 弱引用对象,弱引用在没有被对象引用就会被回收。需要注意一下
垃圾回收
标记清除法:
从根集合遍历所有的引用,从根集合可以遍历到 A ,从 A 可以遍历到C,但是 B 成为了一个不可达的引用,B 对象就会标记为垃圾对象。最后被回收。缺点,会造成内存碎片
复制算法:
把可达的进行复制,复制完了之后把原来的对象全部进行回收,缺点,需要一个交换内存
标记整理算法:
第一个阶段扫描并标记不可达的对象,第二个阶段扫描整个空间并进行整理,在整理的过程中清除标记的对象
垃圾回收触发方式
java 虚拟机无法为新的对象分配内存空间了
手动 System.gc() 方法
底优先级的 GC 线程被运行时就会执行 GC
Dalvik 与 JVM 的不同
执行文件不同,一个是 calss 文件 ,一个是 dex 文件
类加载的系统与 JVM 区别较大的
可以同时存在多个 DVM
dalvik 是基于寄存器的,而 JVM 是基于栈的
ART 比 Dalvik 有哪些优势
DVM 使用 JIT 将字节码转换 机器码,效率低
ART 采用了 AOT 预编译技术,执行速度快,AOT 在应用程序安装的时候将字节码转换成了本地机器码。这个执行的很快
JVM 是基于栈的
ART 比 Dalvik 有哪些优势
DVM 使用 JIT 将字节码转换 机器码,效率低
ART 采用了 AOT 预编译技术,执行速度快,AOT 在应用程序安装的时候将字节码转换成了本地机器码。这个执行的很快
ART 会占用更多的应用安装时间和存储空间