JVM——内存布局、类加载机制及垃圾回收机制

一、JVM内存布局

JVM内存布局也叫做JVM运行时数据区,由以下部分组成:

下面了解各区域的作用(重要):

1> 程序计数器:记录当前指令执行到哪个地址

2> 元数据区:保存当前类被加载好的数据(类名、方法名、方法参数个数等)

3> 栈:保存方法间的调用关系(本地方法栈保存的是本地方法间的调用关系,虚拟机栈保存的是Java方法之间的调用关系)

4> 堆:保存对象


二、JVM类加载

2.1 类加载机制

对于一个类,它的生命周期是这样的:

其中前5步是固定的顺序,也是类加载的流程,具体内容如下(重要):

1)加载

通过类的全限定名(包名+类名)找到.class文件并读取到内存中

2)验证

校验.class文件读取到的内容是否是合法的,并且将这里的内容转化为结构化的数据

3)准备

为类中定义的静态变量分配内存,并设置初始值

4)解析

将常量池中的符号应用改为直接引用

5)初始化

将类对象进行最终的初始化,对对象的各种属性进行填充(如果发现这个类的父类还没有加载,也会触发父类的类加载)


2.2 双亲委派模型

双亲委派模型应用在类加载过程中的加载步骤的,它描述了类加载器(专门用于类的加载)之间的协作关系,JVM默认提供3种类加载器,委派过程如下(重要):


三、垃圾回收机制

3.1 死亡对象的判断算法

JVM中的垃圾回收,实际上是回收对象,以对象为单位,既然要回收垃圾,就需要先找到垃圾,相关算法主要有 1)引用计数算法 2)可达性分析算法

3.1.1 引用计数算法

**算法思想:**给对象增加一个引用计数器,每有一个地方引用,计数器+1,每有一个引用失效,计数器-1,只需要通过判断计数器中的值是否为0来判断对象为垃圾

JVM中并没有使用这种算法,主要是因为这个算法存在循环引用的问题:


3.1.2 可达性分析算法

可达性分析算法是JVM采取的死亡对象判断算法

算法思想: 类似于遍历树/图,JVM会通过一系列称为"GC Root"的对象作为起点,不断向下遍历,遍历到的对象会被标记为可达,没有遍历到的对象会被标记为不可达,不可达的对象会被当作垃圾回收


3.2 垃圾回收算法
3.2.1 标记-清除算法

算法思想: 算法分为"标记"和"清除"两个阶段,首先标记出所有待回收对象,标记完后统一回收所有被标记对象。

缺点:

(1)效率问题: 标记和清除两个过程的效率都不高

(2)空间问题: 会产生内存碎片问题,导致后续需要分配较大对象时不得不提前触发另一次垃圾收集。


3.2.2 复制算法

算法思想: 将内存划分为两份,每次只使用其中一份,将不用回收的对象复制到另一份空间,再将这份空间全部释放。

缺点:

**(1)**空间利用率底

**(2)**如果不是垃圾的对象太多,复制成本很高


3.3.3 标记-整理算法

算法思想: 标记出待回收对象后,将所有存活对象都向一端移动,然后直接释放端边界以外内存(和顺序表删除元素类似,存活对象移动过程中将待删除对象覆盖)

**缺点:**移动过程开销太大


3.3.4 分代算法(JVM采取)

算法思想: 将内存划分为两块,根据存活对象的周期不同(经历的GC次数)分为新生代和老年代,在新生代(Minor)中,每次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法 ;而老年代(Full)中对象存活率高、没有额外空间对它进行分配担保,就必须采用"标记-整理"算法,具体细节如下图:

优点:

**(1)**一般认为,新生代中的大部分对象都会快速消亡,使得每次复制开销可控

**(2)**老年代的对象大部分生命周期较长,使得整理的开销也可控

相关推荐
数据智能老司机1 天前
Akka实战——快速上手
jvm·架构·akka
lichkingyang2 天前
最近遇到的几个JVM问题
java·jvm·算法
lixn2 天前
深入理解JVM字节码:invokedynamic
java·jvm
heeheeai2 天前
jvm对象内存占用
开发语言·jvm·内存分析
编啊编程啊程2 天前
JUC之AQS
java·开发语言·jvm·c++·kafka
努力的小郑3 天前
别再说你会 new Object() 了!JVM 类加载的真相,绝对和你想的不一样
java·jvm·面试
Slaughter信仰3 天前
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第二章知识点问答(21题)
java·开发语言·jvm
whitepure4 天前
万字详解JVM
java·jvm·后端
猿究院--王升5 天前
jvm三色标记
java·jvm·算法