【JVM】 类加载机制、类加载器、双亲委派模型详解

文章目录


前言

📕各位读者好, 我是小陈, 这是我的个人主页

📗小陈还在持续努力学习编程, 努力通过博客输出所学知识

📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽

📙 希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)


提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之处欢迎批评指点~ 废话不多说,直接上干货!

一、类加载机制

类加载是指:把 .class 文件加载到内存, 得到类对象的过程

类加载被分为 5 个步骤:

  • 1, 加载(Loading): 查找并加载这个类的二进制文件(.class文件), 并读取文件内容
  • 2, 验证(Verification): 验证这个二进制文件是否符合《Java虚拟机规范》, 是否有正确的文件格式、是否有正确的访问权限等
    这一阶段的目的是确保 Class 文件的字节 流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全
  • 3, 准备(Preparation): 给类对象(静态变量)分配内存空间, 此时的静态变量都是默认值
  • 4, 解析(Preparation): 将常量池内的符号引用替换为直接引用的过程, 也就是初始化常量的过程

这些常量在.class文件中存在时, 只知道相互之间的相对位置, 并不知道在内存中的实际位置, 这时候的常量就是"符号引用", 加载到内存中后, 这些常量有了自己的内存地址(相对位置不变), 此时的常量就是直接引用

  • 5, 初始化(Initialization): 真正开始执行类中编写的 Java 程序初始化的代码, 将主导权移交给应用程序, 初始化阶段就是执行类构造器方法的过程(初始化静态成员, 执行静态代码块, 如果有父类就去加载父类)

什么时候进行类加载?

并非是JVM一致性, 就把程序中所有的类都加载, 而是非必要不加载, 类似于懒汉模式, 以下三种情况会触发类加载 :

  • 1, 创建了这个类的实例
  • 2, 调用这个类的静态方法
  • 3, 创建了子类的实例 / 调用了子类的静态方法, 会加载当前(父)类

二、类加载器

类加载器(Class Loader)是 Java 虚拟机(JVM)的重要组成部分, 负责将字节码文件加载到内存中并转换为可执行的类

类加载器分为三种 :

  • 启动类加载器(Bootstrap Class Loader):它是 JVM 的内部组件,负责加载 Java 核心类库(如java.lang) 和其他被系统类加载器所需要的类。启动类加载器是由 JVM 实现提供的,通常使用本地代码来实现
  • 扩展类加载器(Extension Class Loader):负责加载 Java 的扩展类库(如 java.util、java.net)等
  • 系统类加载器(System Class Loader):负责加程序员自己写的类以及第三方库中的类

其实还有第四种: 自定义类加载器, 此处就不讨论了


三、双亲委派模型

双亲委派模型是类加载机制中第一步: 查找 .class 文件的过程

具体来说: 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载

双亲委派模型的优点:

  • 避免重复加载类:比如 A 类和 B 类都有一个父类 C 类,那么当 A 启动时就会将 C 类加载起来,那么在 B 类进行加载时就不需要在重复加载 C 类了
  • 安全性:使用双亲委派模型也可以保证了 Java 的核心 API 不被篡改,如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类,而有些 Object 类又是用户自己提供的,因此安全性就不能得到保证了

总结

本篇主要介绍了JVM 中的类加载机制, 分为加载, 验证, 准备, 解析, 初始化五步

在第一步 "加载" 中, 涉及到了 "双亲委派模型" , 而这又建立在三层类加载器的基础上

如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦😋😋😋~


上山总比下山辛苦
下篇文章见

相关推荐
阿龟在奔跑4 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
王佑辉5 小时前
【jvm】方法区常用参数有哪些
jvm
王佑辉5 小时前
【jvm】HotSpot中方法区的演进
jvm
Domain-zhuo5 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
Theodore_10221 天前
7 设计模式原则之合成复用原则
java·开发语言·jvm·设计模式·java-ee·合成复用原则
我是苏苏1 天前
Web开发:ORM框架之使用Freesql的DbFrist封装常见功能
java·前端·jvm
天草二十六_简村人1 天前
Java语言编程,通过阿里云mongo数据库监控实现数据库的连接池优化
java·jvm·数据库·mongodb·阿里云·微服务·云计算
老码沉思录2 天前
Android开发实战班 - 数据持久化 - Room 数据库应用
android·jvm·数据库
起名字真南2 天前
【C++】深入理解 C++ 中的继承进阶:多继承、菱形继承及其解决方案
java·jvm·c++·chatgpt·aigc
偶尔。5352 天前
JVM垃圾回收算法详解
jvm