【JVM神秘大门】Java虚拟机原理的保姆式教学,零基础速成精英之路(上篇)

本篇会加入个人的所谓鱼式疯言

❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言

而是理解过并总结出来通俗易懂的大白话,

小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.

🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!

在这里插入图片描述

引言

当我们谈论 Java 时,JVM 原理就像是一扇神秘的大门,通向程序运行的深层世界。在这扇门后,隐藏着无数的奥秘和惊喜,等待着我们去探索。让我们一起推开这扇门,揭开 JVM 原理的神秘面纱吧!

目录

  1. JVM 内存区域划分

  2. JVM 类加载的过程

  3. 双亲委派模型

一. 内存区域划分

1. 内存区域的引入

在这里插入图片描述

让一个 Java程序 跑起来, 就会 分配进程 , 我们知道进程是 资源分配的基本单位

在 JVM 中为了更好的 管理内存单元 , 于是就把内存分配成 一段一段的不同的区域 ,为了更好的 方便管理和利用

在这里插入图片描述

如上图:

好比在小编的学校中要开发一个校区, 就会把这个 校区用来执行不同的任务的区域 : 教室, 行政楼, 快递站, 食堂等…

这样划分不同的区域不仅可以更好的工作 , 还方便 学校的管理

下面让我们看看JVM 内部的内存区域划分吧 💖 💖 💖 💖

2. JVM 内存区域划分

在这里插入图片描述

如上图, 在JVM 中主要划分为以下区域:

  • 程序计数器 : 记录着需要 执行的下一条指令,注意这里的 程序计数器 执行的 不是CPU的寄存器 , 而是一段 内存空间, 执行的下一条指令是字节码 .class文件

  • : 分为两个不同的栈:
    本地方法栈: 处在 JVM内 是一些由C++ 实现的函数, 存放着函数之间的调用关系
    虚拟机栈: 处在 JVM外是存放着Java代码之间的方法调用关系局部变量

  • :存放着 主要用于存放 类的方法字符串常量, 成员变量 对象 的区域

  • 元数据区(方法区)全局变量静态变量普通常量静态方法 , 函数之间的调用关系。

鱼式疯言

补充说明

  1. 对于JVM 而言, 不是在 操作系统内核上加载进程 , 而是在软件层面上自己实现一套和操作系统相似的读取指令, 加载进程的方式, 处理细节可能不同, 但是执行的思想大体上是相似的。
  1. 当Java创建进程后, 堆和元数据区 只有一份, 因为进程系统分配的基本单位, 但是 在一个进程下可以创建多个线程 , 就会出现多个 程序计数器 , 分别服务 每一个线程

3. 题目测试

class Test {
    private int a;
    private Test b = new Test();

    private static Test d = new Test();

    public static void main(String[] args) {
        int e = 10;
        Test f = new Test();
    }
}

如上面的代码, 问题: 找出变量 a,,b,d,e,f 分别所处的内存区域 。

在判断这些变量所处的内存不分为 是不是内置类型 , 而是看他们所处于的位置和 是否是 static 修饰。

a 和 b 处在 类的内部, 方法的外部 就处在

d 是属于 static 修饰的, 就属于静态方法, 存放在 元数据区(方法区)

e f 处在 类的内部, 并且处在 方法的内部 , 这样的变量我们就处在

鱼式疯言

综上所述

  • 成员变量和成员方法 的处在

  • 静态变量和静态方法 的处在 元数据区

  • 方法内部的局部变量 处在

二. JVM 类加载的过程

在JVM 内部 , 程序是怎么运行的? 他们在JVM 内部又会经历怎么样的过程呢?

大体上分为五步: 加载验证准备解析初始化

1. JVM 的加载流程

<1>. 加载

在JVM 中, 先确定类名, 然后根据类名去查找 字节码文件,涉及到一系列 目录查找的过程 , 找到 .class 文件 之后就 打开并解析文件内容

<2>. 验证

打开.class 文件内容后, 验证.class 的文件数据是否合法, 是否正确。

在这里插入图片描述

因为在 Java标准库 中, 明确规定了 .class 文件 的格式是怎么样的~

<3>. 准备

给需要的 类对象分配内存空间(需要内存) , 根据刚才读到的内容, 确定类对象需要的内存空间, 分配好内存空间, 并 ==把内存空间的所有内容都初始化为 0 == 。

class Test {
    static int a = 10;
}

如上图 , 准备过程就是确定a 的内存空间大小为 4 个字节, 然后 给 a 分配4个字节的内存空间 , 并且 初始化a为0 , 但是要注意一点的是, 准备工作是还没有把 10 赋值给a 的(后面的过程才会出现赋值)

<4>. 解析

主要是把常量字符串通过偏移量解析到文件中。

在这里插入图片描述

在内存中一个存放常量的位置称为 地址, 但在文件中我们就用偏移量的概念来表示。 偏移量就是相对于起始位置的距离, 我们就称之为 偏移量

如上图:

所以上图就是把内存中的 常量abc内存地址 解析到 文件中的偏移量 的过程。

举个栗子理解下解析的过程吧, 假如小编的学校要 进行春游。

然后在一次看电影的环节, 辅导员叫我们按照学号排好位置来看电影。

在这里插入图片描述

于是排好位置, 我的偏移量就相对于 起始位置小张 就为3 , 当我们都坐下后, 也就确定了每一个人 相对于起始位置的偏移量 , 从而确定自身的位置。

<5>. 初始化

针对类对象进行最终的 初始化操作 ,把所有的静态变量都进行 赋值

鱼式疯言

补充说明

在执行 静态代码块 时, 如果 有父类就会对父类进行会对父类先进行加载。 (按照父-> 子顺序加载)

三. 双亲委派模型

1. 双亲委派模型的引入

在类加载过程中有另一个重要的面试题: 双亲委派模型

这是上述类加载过程五个步骤的 第一个步骤的其中一个环节 , 通过类的全限定名,找到 .class 文件 的位置。

在JVM 内部内置一些内加载器, 完成 “类加载”的过程(JVM的功能模块)

其中就有三个默认的加载器:

BooystrapClassLoader : 负责加载标准库中的类 (标准库中的类, 有一个专门存放的位置)

ExtensionClassLoader : 负责加载一些扩展类(JVM 厂商希望对标准库的类做进一步的扩展)

ApplicationClassLoader : 负责加载一些第三方库的类和开发人员自己写的类。

上述三个加载器虽然没有继承关系, 但是有parent 这样的引用会指向上一个类:

儿子: ApplicationClassLoader ->父亲: ExtensionClassLoader -> 爷爷: BooystrapClassLoader 这样的关系。

所以上面的三个加载器, 并不能说是 双亲委派模型(英文翻译的) , 更应该说是 单亲委派模型 / 父亲委派模型, 但是竟然这样翻译, 我们就这样称呼吧。

2. 双亲委派模型的流程

在这里插入图片描述

如上图

如果我们要寻找 java.lang.String 这个类。

首先从儿子出发, 儿子这边不会先查找, 而是先交给父亲, 当交到父亲手上也不会先查找, 而是再交给爷爷。

由爷爷先查找标准库中是否有 String 这个类, 如果找到了就 直接进行类加载的2,3, 4,5 的步骤

如果 爷爷没找到就就会返回给父亲找 , 找到就和上面一个继续进行下面类加载的步骤, 如果没有就交给儿子来寻找。

儿子也是如此, 但是 儿子如果没有找到就会抛出异常 ClassNotFoundException 这个异常, 告诉开发人员这个类没有找到。

鱼式疯言

栗子理解

好比像在公司平常的工作任务一样。

当小编一个小员工, 接收到一个任务时, 就需要 请示领导 该怎么样去做, 然后领导

这边也要继续请示大领导。 当大领导觉得这件事情很重要时,就会自己留下来处理。

当大领导觉得 这件事不是那么重要 , 就会交回给我的领导去做, 我的领导看了看觉得 没有那么重要的话, 就会交给我去做, 否则就会留下自己去做。

3. 双亲委派模型的优点

之所以想上面的流程一样, 需要先不断向上传递优先查找, 就是要保证优先级顺序: 标准库扩展库第三方库

保证 标准库的优先级是最高的, 其次是 扩展库, 最后是 第三方库

这样做的好处就在于, 可以保证 标准库的代码先执行到 , 以免因为 第三方库自己写的代码和标准库重名 , 而造成 意想不到的BUG 出现

总结

  • JVM 内存区域划分: 对于JVM 内存主要划分为: 程序计数器, 栈, 堆 , 元数据区(方法区) , 理解他们的不同区域的含义以及不同位置上的变量所处于区域划分。

  • JVM 类加载的过程: 加载 ——》 验证——》准备——》 解析——》初始化 , 按照这样的流程来 加载 .class 文件

  • 双亲委派模型 : JVM 类加载五个步骤中的第一个步骤的一个环节, 了解JVM 中默认的三个加载器, ApplicationClassLoaderExtensionClassLoaderBooystrapClassLoader 分别对应着: 标准库扩展库第三方库。 并且从双亲委派模型中确认优先级 标准库 》 扩展库》 第三方库 , 保证标准库优先被执行到, 以免出现 BUG。

如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正

希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 💖 💖 💖

在这里插入图片描述

评论 69
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邂逅岁月

感谢干爹的超能力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值