Java虚拟机的类加载机制
Java虚拟机的类加载机制
- 综述
- 类的生命周期
- 类加载器
- 双亲委派模型
- ---
综述
我们编写的Java代码如何能在一个操作系统上运行呢?一般来说,我们使用javac命令将.java文件编译成.class文件,也就是Java字节码文件,然后由JVM将字节码文件加载到JVM内存中,在运行时,一方面由解释器将字节码解释为一行行的机器码来执行,另一方面,由即时编译器针对热点代码,将其编译成机器码以获取更高的执行效率,解释器和即时编译器的相互配合使程序几乎能够达到和编译型语言一样的执行速度。其中JVM加载字节码的过程就是类加载。类加载的目的从高处看是为了将字节码文件转换成内存中某种形式的Class数据结构,程序可以通过这种数据结构构造出object,而这个过程是在运行时进行的,这也是Java动态扩展性的根基。从地处看,一个Java类从被加载到内存中开始,到卸载出内存为止,它将经历加载、验证、准备、解析、初始化、使用和卸载这七个阶段,其中验证、准备和解析可以统称为连接。而类加载只包括其中加载、连接和初始化这三个阶段。解析阶段是灵活的,可以在初始化阶段之前进行,也可以在初始化之后进行(动态绑定)。
类的生命周期
加载阶段是读取字节码文件,将其转化为某种静态数据结构存储在方法区中,并在堆中生成一个便于用户调用的java.lang.Class类型的对象的过程。
验证阶段是对字节码文件的规范校验,主要包括文件格式验证、元数据验证、字节码验证和符号引用验证。其中文件格式的验证是发生在加载阶段的,通过验证才能顺利加载。顺利加载后,方法区才有该类的数据结构,堆中也有该类的Class对象,但并不代表该类可以使用,还需要对该类的静态结构进行验证,包括元数据与字节码验证,主要是对其进行语法和语义分析,保证其不会产生危害虚拟机的行为,符号引用的验证发生在解析阶段。
准备阶段就是对类中定义的静态变量分配内存并初始化,在JDK8以前,hotspot使用永久代实现的方法区,所以类的元数据、常量池、静态变量等数据存放在永久代,而JDK8及以后,hotspot使用元空间实现了方法区,并将常量池和静态变量移到了堆上
解析阶段主要是将符号引用替换为直接引用,那么什么是符号引用,什么又是直接引用呢?我的理解是如果一个类A中引用了类B,但是B还没加载,那么A中对于B的引用在解析阶段之前是不知道B的地址的,所以A中会使用一个符号来代替B的地址,直到A进行到解析阶段,发现需要B的地址,由此触发B的加载,待到B加载完成之后,A中对B的引用符号会被B的真实地址所替换,那么那个替代符号就是指符号引用,后面真实地址则是指直接引用。而对于多态,B则可能是一个抽象类或接口,此时B的实现并不明确,那么其符号引用的替换则需要等到其运行调用时,虚拟机调用栈中会得到具体的类型信息,这时候再进行直接引用的替换,这就是动态解析,而前面就是静态解析。有时候解析发生在初始化阶段之后,这就是动态解析,用来实现后期绑定
初始化阶段是对类中的主动的资源初始化动作,也就是执行对静态变量和成员变量赋用户值以及静态代码块的逻辑
类加载器
在类加载过程中,用户主导的部分就是加载阶段获取二进制字节流部分和初始化阶段,其余部分全由JVM主导,则是符合开闭原则的。JVM规范中定义了两类类加载器:启动类加载器和其他类加载器,hotspot中则定义了四种类型的类加载器:C++实现的启动类加载器和Java实现的、继承自java.lang.ClassLoader的扩展类加载器、应用程序类加载器和用户自定义类加载器。其中启动类加载器无法作为对象被引用,用于加载lib下面的包,扩展类加载器用于加载lib/ext下的包,应用程序类加载器用于加载classpath下的包,用户自定义类加载器可以加载任意用户指定路径下的包
双亲委派模型
为什么要指定这么多类加载器呢?不能只有有一个吗?原则上可以只有一个的,但不太适合扩展,所以采用类似分类别类,对于系统需要的,则专门使用一个,而对于用户扩展的,则使用另一个或用户自己创建,这就解决了扩展性问题,但这又带来了一个新问题,那就是对于同一个限定名的类,不同类加载器会产生不同的类吗?设计者给出的解决方案是不同类加载器加载同一限定名的类会产生不同的类,因为xx,但是如果我想让它是同一个呢?这就要提到双亲委派模型了,双亲委派模型是指对于加载请求,子类会先委派给父类加载,如果父类不能加载,则再委派到子类加载,这里实现的方式是通过组合而非继承。越核心的类库会被越上层的类加载器所加载,而某限定名的类一旦被加载,在被动情况下,就不会再加载相同限定名的类了,这样就有效避免了加载的混乱。关于双亲委派模型的四次破坏:①是
—
类加载机制=类的生命周期+类加载器+双亲委派模型
机制是指系统中各要素相互作用的过程和方式,Java虚拟机的类加载机制是指被编译好的Java字节码(Class文件)在被加载到Java虚拟机内存中开始,到形成可被Java虚拟机直接使用的Java类型为止的整个过程和相关方式,所以要理解类加载机制,就不可避免的要谈到Java类的生命周期与双亲委派模型了。
一个Java类型从被加载到虚拟机内存中开始,到卸载出内存为止,它将经历加载、验证、准备、解析、初始化、使用和卸载这七个阶段,其中验证、准备和解析这三个阶段可以统称为连接。而类加载则包括指加载、连接和初始化这三个阶段。
在代码被编译器编译成字节码之后,由相应的类加载器开始加载字节码,首先会通过类的全限定名获取该类的二进制字节流,然后将这个二进制字节流所代表的静态存储结构转化为方法区的运行时数据结构,并在内存中生成一个代表该类的java.lang.Class对象,作为该类各种数据的访问入口(加载阶段)。在获取到类的二进制字节流的同时,会进行文件格式、元数据、字节码和符号引用的验证,以确保该二进制字节流所包含的信息符合Java虚拟机的规范要求,保证被当作代码运行后不会危害到虚拟机自身的安全(验证阶段)。验证通过之后,会为类中定义的静态变量分配内存并初始化数值(准备阶段负责分配内存和赋缺省值,初始化阶段负责赋用户值)。同时,将常量池中的符号引用替换成直接引用(解析阶段)。然后用户就可以使用该类了(使用阶段、卸载阶段)。
参考:
《深入理解Java虚拟机(第三版)》
相关文章:
Java虚拟机的类加载机制
Java虚拟机的类加载机制综述类的生命周期类加载器双亲委派模型---综述 我们编写的Java代码如何能在一个操作系统上运行呢?一般来说,我们使用javac命令将.java文件编译成.class文件,也就是Java字节码文件,然后由JVM将字节码文件加…...
分治法实现合并排序(归并排序),理解分治算法思想,实现分治算法的完美例子合并排序(含码源与解析)
🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨,经典算法的解析✨都在这儿,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 -…...
Typescript 类 (class)
基本用法 (通过关键字 class) // 基本用法 class VueService {constructor() {} // 构造器 } 类的约束(通过关键字 implements) // 接口定义属性类型 interface VueProps {name: stringinit: () > void }// 约束类 class VueService implements Vue…...
KDZD程控超低频高压发生器
一、产品概述 本产品接合了现代数字变频技术,采用微机控制,升压、降压、测量、保护自动化。由于电子化,所以体积小重量轻、大屏幕液晶显示,清晰直观、且能显示输出波形、打印试验报告。 设计指标符合《电力设备专用测试仪器通用…...
【华为OD机试 2023最新 】 过滤组合字符串(C++)
文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 数字0、1、2、3、4、5、6、7、8、9分别关联 a~z 26个英文字母。 0 关联 “a”,”b”,”c”1 关联 “d”,”e”,”f”2 关联 “g”,”h”,”i”3 关联 “j”,”k”,”l”4 关联 “m”,”n”,”o”5 关联 “p”,”q”…...
Java笔记034-坦克大战【2】
目录 坦克大战【2】 线程-应用到坦克大战 坦克大战0.3 思路分析: 代码实现: 坦克大战0.4 增加功能 特别说明 思路分析: 代码实现: 坦克大战0.5 增加功能 思路分析: 代码实现: 坦克大战【2】 …...
【算法】【数组与矩阵模块】桶排序思想解决无序数组排序后相邻数间的最大差值
目录前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本思考感悟写在最后前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识! 问题介绍 …...
C语言—函数
函数库函数自定义函数函数的参数函数的调用函数的嵌套调用和链式访问函数的声明和定义函数递归递归与迭代函数递归的经典题目维基百科(台湾方面维护的,翻译形式跟大陆有所差异)中对函数的定义:子程序在计算机科学中,子…...
Autosar模式管理实战系列03-基于Davinci工具的WDGM配置
本文框架 前言1.WdgMConfigSet 配置2. 新建监控实体(SE)2.1 新建检测点(Checkpoint)2.2 设置 WdgMInternalTransitions3. WdgMLocalStatusParams配置4. WdgMAliveSupervision配置5. 代码插入指导前言 前面我们介绍了WdgM(看门狗管理)是一个 AutoSAR 的基础模块,负责管理看门…...
AutoML-sklearn and torch
一、auto-sklearn 1.1 环境依赖 额外安装swig 第三方库 linux 支持, mac,windows不支持 1.2 示例代码 time_left_for_this_task 设定任务最大时间 per_run_time_limit 每个子任务最大训练时间 include 可以限制任务训练的模型 import autosklearn.classific…...
《扬帆优配》算力概念股大爆发,主力资金大扫货
3月22日,9股封单金额超亿元,工业富联、鸿博股份、鹏鼎控股分别为3.01亿元、2.78亿元、2.37亿元。 今日三大指数团体收涨,收盘共34股涨停,首要集中于数字经济方向,其间云核算、CPO大迸发。除去5只ST股,算计2…...
机械臂+底盘三维模型从solidworks到moveit配置功能包
文章目录 导出底盘STEP加载机械臂模型组合机械臂和底盘三维模型导出URDF在moveit中进行配置新建工作目录设置ROS工作空间的环境变量进入moveit setup加载URDF文件self-CollisionsPlanning groupsRobot posesControllersSimulationAuthor information生成配置包在rviz中进行可视…...
高并发系统设计:缓存、降级、限流、(熔断)
高并发系统设计:缓存、降级、限流、(熔断) 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。 非核心服务可以采用降级、熔断,核心服务采用缓存和限流(隔离流量可以最大限度的保障业务无损)。 缓存 缓…...
《辉煌优配》放量大涨,A股成交额重回万亿!PCB板块继续领跑
多只绩优PCB概念股超跌。 今日A股放量反弹,成交额从头站上万亿关口。芯片板块掀涨停潮,景嘉微、芯原股份20cm涨停,紫光国微、兆易创新、跃岭股份等封板;AI算力、存储器、光模块、云核算等板块全线拉升,板块内个股再度批…...
Vue封装的过度与动画
动画效果 先把样式封装好,然后设置一个动画 不需要vue也能实现的动画的效果,我们只需要判断一下,然后动态的添加和删除类名即可 那能不能不自己写动态,就靠vue 首先我们要靠<transition>标签把需要动画的包裹起来 vue中…...
流量监控-ntopng
目录介绍安装使用介绍 ntopng是原始ntop的下一代版本,ntop是监视网络使用情况的网络流量探测器。ntopng基于libpcap,并且以可移植的方式编写,以便实际上可以在每个Unix平台,MacOSX和Windows上运行。 ntopng(是的&…...
C++ 21 set容器
目录 一、set容器 1.1 简介 1.2 构造和赋值 1.3 大小和交换 1.4 插入和删除 1.5 查找和统计 1.6 set和multiset区别 1.7 内置类型指定排序规则 1.8 自定义数据类型指定排序规则 一、set容器 1.1 简介 ① set容器中所有元素在插入时自动被排序。 ② set容器和multise…...
什么是JWT
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。 传统的session认证 http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一…...
Gradle7.4安装
前置:本文基于IntelliJ IDEA 2022.2.1 、jdk1.8进行安装 目录 1.挑选Gradle版本 2.系统变量设置 1.挑选Gradle版本 gradle兼容性差, 1.跟idea会有版本问题。 2.跟springboot也有兼容问题Spring Boot Gradle Plugin Reference Guide 首先查询版本&…...
【华为OD机试 2023最新 】 箱子之字形摆放(C++ 100%)
文章目录 题目描述输入描述输出描述备注用例题目解析C++题目描述 有一批箱子(形式为字符串,设为str), 要求将这批箱子按从上到下以之字形的顺序摆放在宽度为 n 的空地,请输出箱子的摆放位置。 例如:箱子ABCDEFG,空地宽度为3,摆放结果如图: 则输出结果为: AFG BE CD …...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
