jvm类加载机制概述

18bd9cc6225d45bcb0898827946949eb.jpg、什么是jvm的类加载机制

 

  类加载机制是指我们将类的字节码文件所包含的数据读入内存,同时我们会生成数据的访问入口的一种 特殊机制。那么我们可以得知,类加载的最终产品是数据访问入口。

 

  加载类文件(即.class文件)的方式有以下几种:

 

从本地系统中直接加载。

通过网络下载的.class文件。比如Web Applet,也就是我们的小程序应用。

从war,jar等归档文件中加载class。

从专有数据库中提取.class文件。

将java源文件动态编译为.class文件,也就是运行时计算而成,java的动态代理技术就是这么实现的。

从加密文件中获取。典型的防止class文件被反编译的保护措施。

回到顶部

2、类装载的过程

  类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个过程包括:装载、验证、准备、解析、初始化、使用、卸载7个阶段。其中验证、准备、解析统称为链接。如下图     

 

 

 

 

 

装载(Loading):

通过一个类的全限定名获取定义此类的二进制字节流,由上文可知,我们不一定从字节码文件中获取字节流,还能通过上述多种方式获取字节流。

将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

在java堆中生存一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入库。 

      获取类的二进制字节流的阶段是我们java程序员最关注的阶段,也是操作性最强的一个阶段,因为这个阶段我们可以对我们的类加载器进行操作 ,比如我们想自定义类加载器进行操作完成加载,又或者我们想通过java agent来完成我们的字节码增强操作。

 

连接(Linking):

验证(Verification):验证主要是为了保证被加载类的正确性,即装载的Class文件中的字节流保护的信息是否符合当前虚拟机的要求,并且还要求我们的信息不会危害虚拟机自身的安全,导致虚拟机的崩溃。这其中包括四个阶段:

文件格式的验证:第一阶段要验证字节流是否符合class文件格式的规范,并且能被当前版本的虚拟机处理

元数据的验证:第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求。

字节码验证:第三阶段是整个验证过程中最复杂的一个阶段,主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。在第二阶段对元数据信息中的数据做完校验后,这个阶段将对类对方法体进行校验分析,保证被校验类对方法在运行时不会做出危害虚拟机安全对事件。

符号引用验证:这是最后一个阶段的验证,它发生在虚拟机将符号引用转化为直接引用的时候(解析阶段), 可以看作是对类自身以外的信息(常量池中的各种符号引用)进行匹配性的校验。符号引用 验证的目的是确保解析动作能正常执行。

准备(Preparation):为类的静态变量分配内存,并将其初始化为默认值。

解析(Resolution):

初始化(Initialization):

    初始化阶段是执行类构造器()方法的过程。在准备阶段,类变量已赋过一次系统要求对初始值,而在初始化阶段,则是根据程序员通过程序制定的主观计划去初始化类变量和其他资源,比如赋值。

 

    在java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻“初始化”(加载,验证,准备,自然需要在此之前开始):

 

使用new关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类。

初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化。

使用java.lang.reflect包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化。

虚拟机启动时,用户会先初始化要执行的主类(含有main)

jdk 1.7后,如果java.lang.invoke.MethodHandle的实例最后对应的解析结果是 REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法所在类没有初始化,则先初始化。

使用(Useing):

主动使用:

创建类的实例,也就是new的方式

访问某个类或接口的静态变量,或者对该静态变量赋值

调用类的静态方法

反射

初始化某个类的子类,则其父类也会进行初始化

java虚拟机启动时被标明为启动类的类(SpringbootApplication类)

被动使用:

引用父类的静态字段,只会引起父类的初始化,而不会引起子类的初始化

定义类数组,不会引起类的初始化      

引用类的static final常量,不会引起类的初始化(如果只有static修饰,还是会引起该类初始化 的)

 

卸载(Unloading):    

    在类使用完成之后,如果满足下面的情况,类就会被卸载:

 

该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例

加载该类的ClassLoader已经被回收

该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法 

 

  如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类对卸载过程其实就是在方法区中清空类信息,java类对整个生命周期就结束类。但是一般情况下启动类加载器加载的类不会被卸载,而我们的其他两种基础类型的类加载器只有极少的情况下才会被卸载。

 

回到顶部

3、类的加载器

  java的类记载器是负责读取java字节码,并转换成java.lang.class类的一个实例的代码模块。类加载器除了用于加载类外,还可以用于确定类在java虚拟机的唯一性。  

 

      一个类在同一个类加载器中具有唯一性(Uniqueness),而不同类加载器中是允许同名类存在的, 这里的同名是指全限定名相同。但是在整个JVM里,纵然全限定名相同,若类加载器不同,则仍 然不算作是同一个类,无法通过 instanceOf 、equals 等方式的校验。

 

  java虚拟机自带有以下三种类加载器:

 

Bootstrap ClassLoader

负责加载$JAVA_HOME中 jre/lib/rt.jar 里所有的class或Xbootclassoath选项指定的jar包。由 C++实现,不是ClassLoader子类。

Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs 指定目录下的jar包。

Application ClassLoader  

负责加载classpath中指定的jar包及 Djava.class.path 所指定目录下的类和jar包。

 

 

  除此之外,用户也可以自定义类加载器:

 

User ClassLoad

通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的 ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。

 

  

 

 

 

回到顶部

4、双亲委派机制

  “双亲委派”是指子类加载器如果没有加载过该目标类,就先委托父类加载器加载该目标 类,只有在父类加载器找不到字节码文件的情况下才从自己的类路径中查找并装载目标类。

 

  

 

  “双亲委派”机制加载Class的具体过程是:

 

ClassLoader先判断该Class是否已加载,如果已加载,则返回Class对象;如果没有则委托 给父类加载器。

 

父类加载器判断是否加载过该Class,如果已加载,则返回Class对象;如果没有则委托给祖 父类加载器。

 

依此类推,直到始祖类加载器(引用类加载器)。

 

始祖类加载器判断是否加载过该Class,如果已加载,则返回Class对象;如果没有则尝试从其对应的类路径下寻找class字节码文件并载入。如果载入成功,则返回Class对象;如果载入失败,则委托给始祖类加载器的子类加载器。

 

始祖类加载器的子类加载器尝试从其对应的类路径下寻找class字节码文件并载入。如果载入成功,则返回Class对象;如果载入失败,则委托给始祖类加载器的孙类加载器。

 

依此类推,直到源ClassLoader。

 

源ClassLoader尝试从其对应的类路径下寻找class字节码文件并载入。如果载入成功,则返回Class对象;如果载入失败,源ClassLoader不会再委托其子类加载器,而是抛出异常。

 

 

 

 

 

 

 

  “双亲委派”机制只是Java推荐的机制,并不是强制的机制。我们可以继承java.lang.ClassLoader类,实现自己的类加载器。如果想保持双亲委派模型,就应 该重写findClass(name)方法;如果想破坏双亲委派模型,可以重写loadClass(name)方法。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

处理 Oracle 数据库表空间满的问题

处理 Oracle 数据库表空间满的问题 1、诊断表空间满的问题2、处理表空间满的问题3、设置表空间自增结论 在 Oracle 数据库管理中,表空间是一个重要的概念,用于存储数据库对象和数据。当表空间满了时,可能会导致数据库的运行受到影响&#xff…

Mac 下安装maven教程

note:网上已经有很多该类型教程了,这边自身保留一份,方便后面使用; 一、安装地址:官网 二、安装步骤 $ tar -xvf apache-maven-3.3.9-bin.tar.gz //mac支持手动点击解压 $ sudo mv -f apache-maven-3.3.9 /usr…

服务器固定IP(固定出口IP)去访问外部服务

背景 服务器上有多个IP,那么在服务器请求外部服务的时候,到底是使用哪个IP呢?如果要使用特定的IP去请求外部服务,该如何设置呢? 分析 遇到一个实际的场景: 我们产品和其他产品联调,我们的服务…

Linux中断管理:(一)中断号的映射

文章说明: Linux内核版本:5.0 架构:ARM64 参考资料及图片来源:《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址: zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 中断控制器 Linux 内核支持众多…

规划控制如何兼顾安全与舒适性

规划控制如何兼顾安全与舒适性 附赠自动驾驶学习资料和量产经验:链接 **导读:**自动驾驶技术研发对于“安全第一”的追求是毋庸置疑的,但是这中间可能就忽视了舒适性。 因此,今天我想给大家分享的是,自动驾驶研发如何…

《Java面试自救指南》(专题一)操作系统

文章目录 力推操作系统的三门神课操作系统的作用和功能线程、进程和协程的区别并行与并发的区别什么是文件描述符操作系统内核态和用户态的区别用户态切换到内核态的方式大内核和微内核的区别用户级线程和内核级线程的区别线程的七态模型进程调度算法有哪些进程间通信的七种方式…

zookeeper如何管理客户端与服务端之间的链接?(zookeeper sessions)

zookeeper客户端与服务端之间的链接用zookeeper session表示。 zookeeper session有三个状态: CONNECTING, ASSOCIATING, CONNECTED, CONNECTEDREADONLY, CLOSED, AUTH_FAILED, NOT_CONNECTED(start时的状态) 1、CONNECTING 。 表明客户…

【Linux2】Linux的权限

思维导图 学习内容 在介绍完一些基本指令后,我们需要进行对权限以后一个全新的认识,比如文件的权限、目录的权限等等…… 学习内容 通过上面的学习目标,我们可以列出要学习的内容: shell命令以及运行原理Linux权限的概念Linux权…

【Blockchain】GameFi | NFT

Blockchain GameFiGameFi顶级项目TheSandbox:Decentraland:Axie Infinity: NFTNFT是如何工作的同质化和非同质化区块链协议NFT铸币 GameFi GameFi是游戏和金融的组合,它涉及区块链游戏,对玩家提供经济激励&#xff0c…

失物招领(源码+文档)

失物招领(小程序、ios、安卓都可部署) 文件包含内容程序简要说明含有功能项目截图客户端首页注册界面发布动态我的详细登录修改资料发布动态 管理端后台登录用户管理分类管理内容管理 文件包含内容 1、搭建视频 2、流程图 3、开题报告 4、数据库 5、参考…

施耐德 PLC 控制系统 产品 + 软件总体介绍 2020

参考 2020.7 官方说明视频:https://www.bilibili.com/video/BV1Mi4y1G7Qc/ 总体说明 施耐德作为工业控制界巨头(公认的几大巨头:西门子、AB、施耐德),PLC 控制器产品线很庞大,涵盖了高中低的完整产品线&…

webpack打包模块

webpack打包模块 一.webpack简介二.Webpack 修改入口和出口三.Webpack 自动生成 html 文件四.Webpack-打包 css 代码五.优化-提取 css 代码六.优化压缩过程七.Webpack-打包图片 一.webpack简介 1.Webpack 是一个静态模块打包工具,从入口构建依赖图,打包…

吴恩达2022机器学习专项课程(一) 4.4 学习率

问题预览/关键词 学习率太小有什么影响?学习率太大有什么影响?如果成本函数达到局部最小值,使用梯度下降还能继续最小化吗?为什么学习率固定,而最小化成本函数的步幅却越来越缓?如何选择合适的学习率&…

算法学习——LeetCode力扣图论篇3(127. 单词接龙、463. 岛屿的周长、684. 冗余连接、685. 冗余连接 II)

算法学习——LeetCode力扣图论篇3 127. 单词接龙 127. 单词接龙 - 力扣(LeetCode) 描述 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk: 每一对相…

【苹果MAC】苹果电脑 LOGI罗技鼠标设置左右切换全屏页面快捷键

首先键盘设置->键盘快捷键 调度中心 设置 f1 f2 为移动一个空间(就可以快捷移动了) 想要鼠标直接控制,就需要下载官方驱动,来设置按键快捷键,触发 F1 F2 安装 LOGI OPTIONS Logi Options 是一款功能强大且便于使用…

Spring Boot单元测试全指南:使用Mockito和AssertJ

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

Verilog语法回顾--用户定义原语

目录 用户定义原语 UDP定义 UDP状态表 状态表符号 组合UDP 电平敏感UDP 沿敏感时序UDP 参考《Verilog 编程艺术》魏家明著 用户定义原语 用户定义原语(User-defined primitive,UDP)是一种模拟硬件技术,可以通过设计新的原…

人工智能产业应用--具身智能

五、下一个浪潮 (一) 跳出缸中脑——虚实结合 在探索人工智能的边界时,“跳出缸中脑——虚实结合”这一概念提出了一个引人深思的视角,尤其是在具身智能的领域。具身智能是一种思想,强调智能体通过与其环境的直接物理互动来实现智能行为。然…

QT-左框选项卡软件界面框架

QT-左框选项卡软件界面框架 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include <QTextBrowser> #include <QLabel> #include <QPushButton> #include <QSpacerItem> #include <QToolButton> #include <QDebug> #i…

【MyBatis】MyBatis的介绍和基本使用

目录 一、数据库操作框架的历程 1.1 JDBC 1.2 DBUtils 1.3 Hibernate 1.4 Spring JDBC&#xff1a;JDBCTemplate 1.5 Spring Data JPA 二、什么是MyBatis&#xff1f; 2.1 传统JDBC与MyBatis相比的弊病 2.2 MyBatis中的组件 2.3 MyBatis的体系结构 三、快速搭建MyBa…