自学内容网 自学内容网

JVM类加载基本流程及双亲委派模型

1.JVM内存区域划分

一个运行起来的Java进程就是一个JVM虚拟机,这就需要从操作系统中申请一片内存区域。JVM申请到内存之后,会把这个内存划分为几个区域,每个区域都有各自的作用。

一般会把内存划分为四个区域方法区(也称 "元数据区"),堆区栈区程序计数器

(1)方法区:存储的内容是 "类对象"

(2)堆区:new()出来的对象就存储在堆区。

(3)栈区:存储的内容一般是 一些 方法的形参,方法的返回值,局部变量

(4)程序计数器:程序计数器中存放的是接下来要执行的指令的地址

一个示例代码,看看每个变量存放在内存的哪个区域:

name是"static成员",是"静态变量",也就是"类成员",因此 该变量在 方法区

age是"成员变量",new 出来的对象就会包含age这个属性,因此age变量在 堆区

demo是"局部变量",是一个 "引用类型" 的变量,存放的是 对象的地址。通过demo变量能够找到Demo对象。因此,demo存储在 栈区

                                        

2.JVM类加载的基本流程

我们编写的Java代码会被编译成.class文件,一个Java程序想要运行起来,就得找到.calss文件,把.class文件中的内容 构造成 "类对象",保存到内存的方法区中。以上过程就是类加载的过程。

类加载的过程可以分成5个步骤:加载验证准备解析初始化

(1)加载:找到.class文件,打开文件 并读取文件的内容。

(2)验证:.class文件是一个二进制文件,需要验证当前读取的格式是否符合要求。

(3)准备:给类对象分配内存空间

(4)解析:针对类对象中包含的字符串常量进行处理,进行一些初始化操作。

(5)初始化:对 类对象进行初始化,把类对象中的各个属性都设置好。以及涉及到的static成员,静态代码块等。

3.双亲委派模型

双亲委派模型 属于类加载流程中的第一步,也就是 "加载"过程所涉及到的。这个模型 会根据 全限定类名 找.class文件。

JVM内置了三个 类加载器,分别为 BootStrap ClassLoader(爷)、Extension ClassLoader(父)、Application ClassLoader(子)。

在找.class文件时,会根据类的全限定类名,形如"java.lang.String",从类加载器中寻找该类。

(1)首先,会把Application ClassLoader作为入口,开始执行查找的逻辑。但Application ClassLoader不会立即区扫描自己负责的目录(搜索当前目录和第三方库对应的目录),而是会把这个查找任务 交给自己的父加载器 Extension ClassLoader

(2)那么Extension ClassLoader加载器,也不会立刻去扫描自己负责的目录(负责JDK中的一些扩展的库对应的目录),而是把查找任务 交给自己的父加载器BootStrap ClassLoader

(3)则BootStrap ClassLoader 也不想立刻去扫描自己负责的目录(标准库的目录),于是尝试去把查找任务给到其它的类加载器,但是它没有"父亲",它只能亲自去扫描标准库的目录。

(4)"java.lang.String"能够在标准库中找到对应的.class文件,就可以打开并读取文件,那么寻找.class文件的任务就完成了。

(5)如果给定的类不是标准库的类,那么BootStrap ClassLoader在标准库中就找不到.class文件,还是会把查找任务交给"孩子"来执行。

(6)那么任务就会回到Extension ClassLoader加载器,它就会扫描自己负责的扩展库的目录。如果找到了,查找.class任务就结束了;若没找到,还是把任务交给"孩子"执行

(7)任务就又回到了Application ClassLoader类加载器,它就会去扫描自己的当前目录和第三方库目录。若找到了,找.class文件任务结束;若没找到,就会抛出ClassNotFoundException

以上寻找.class文件过程的模型就是"双亲委派模型",其实就是一个 查找优先级 的问题。率先在标准库中去查找.class文件,若没找到,就去扩展库中去找,再找不到,就去第三方库去找,还找不到,就会抛出异常。


原文地址:https://blog.csdn.net/m0_67872788/article/details/137911635

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!