【03】Java虚拟机是如何加载Java类的

从class文件到内存中的类,按先后顺序需要经过加载、链接以及初始化三个步骤

一、加载

加载就是查找字节流,并且据此创建类的过程。

除了启动类加载器(所有类加载器的祖师爷,由C++实现,没有对应的Java对象)之外,其他的类加载器都是 java.lang.ClassLoader 的子类。这些类加载器需要先由另一个类加载器,比如说启动类加载器加载至JVM中,才能进行类加载。

双亲委派模型:每当一个类加载器接收到加载请求时,它会先将请求转发给父类加载器,在父类加载器没有找到所请求的类的情况下,该类加载器才会尝试去加载。

Java9之前:
启动类加载器 :加载最基础和最重要的类(JRE的lib目录下jar包中的类)。
扩展类加载器 :其父类加载器是启动类加载器,负责加载相对次要,但通用的类(JRE的lib/ext目录下jar包中的类)。
应用类加载器:其父类加载器是扩展类加载器,负责加载应用程序路径下的类(这里的应用程序路径,是指虚拟机参数 -cp/-classpath、系统变量Java.class.path或环境变量CLASSPATH所指定的路径)默认情况下,应用程序中包含的类便是由应用类加载器加载的。

Java9之后:引入模块系统
扩展类加载器 rename为 平台类加载器

除了由 Java 核心类库提供的类加载器外,我们还可以加入自定义的类加载器,实现特殊的加载方式,eg 可以对class文件进行加密,加载时再利用自定义的类加载器对其解密。

在JVM中,类的唯一性是由类加载器实例以及类的全名一同确认。即使是同一串字节类,经由不同类加载器加载,也会得到两个不同的类。

二、链接

链接,是指将创建成的类合并至JVM中,使之能够执行的过程,分为三个如下阶段

Created with Raphaël 2.3.0 验证(确保被加载类能满足JVM的约束条件) 准备(为被加载类的静态字段分配内存) 解析(将符号引用解析成为实际引用)

注意:在class文件被加载至JVM之前,该类无法知道其他类及方法、字段对应的具体地址,甚至不知道自己方法、字段的地址,因此,每当需要引用这些成员时,Java编译器会生成一个符号引用(java编译器会暂时使用符号引用表表示目标方法),在运行阶段,该符号引用一般能无歧义的定位到具体目标,解析的目的就是将这些符号引用解析成为实际引用
当然,这些符号引用有可能指向一个未被加载的类或类的字段,那么解析也将触发这个类的加载(但未必触发这个类的链接及初始化)

1.非接口符号引用

假定该符号引用指向C类

Created with Raphaël 2.3.0 在C中查找符合名字及描述符的方法 未找到,则找C父类直到Object类 未找到,则找C直接或间接实现的接口中搜索
2.接口符号引用

假定该符号引用指向接口I

Created with Raphaël 2.3.0 在I中查找符合名字及描述符的方法 未找到,在Object类中的公有实例方法中搜索 未找到,则在I的超接口中搜索

经过上述解析步骤后,符号引用会被解析成实际引用。
对于静态绑定的方法调用而言,实际引用是一个指向方法的指针;对于动态绑定的方法调用而言,实际引用是一个方法表的索引

三、初始化

只有当初始化完成以后,类才正式成为可执行的状态。

JVM进行类的初始化之前,先简单了解下Java编译器都做了什么工作。
对于Java中初始化,静态字段的初始化有点特殊,
两种方式初始化一个静态字段,
(1)声明时直接赋值(若直接赋值的静态字段被final所修饰,且它的类型是基本类型或字符串时,该字段便会被编译器标记成常量,其初始化直接由JVM完成)
(2)在静态代码块中对其赋值。

所以除了对于常量是直接由JVM完成,其余的初始化(直接赋值操作及所有静态代码块中的代码),会被Java编译器置于同一个方法中,并把它命名为***< clinit >***。

总结为一句话就是,类加载的最后一步初始化,便是为标记为常量 的字段赋值以及执行***< clinit >***方法的过程。

类的初始化仅会被执行一次,这个特性被用来实现单例的延迟初始化。如下demo

public class Singleton {private Singleton() {}private static class LazyHolder {static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return LazyHolder.INSTANCE;}
}

这段代码是著名的单例延迟初始化例子,只有当调用Singleton.getInstance 时,程序才会访问LazyHolder.INSTANCE,才会触发对 LazyHolder 的初始化(对应下图第 4 种情况),继而新建一个 Singleton 的实例

![image.png-74.8kB][1]

个人思考

public class Singleton {private Singleton() {}private static class LazyHolder {static final Singleton INSTANCE = new Singleton();static {System.out.println("LazyHolder.<clinit>");}}public static Object getInstance(boolean flag) {if (flag) return new LazyHolder[2];return LazyHolder.INSTANCE;}public static void main(String[] args) {getInstance(true);System.out.println("----");getInstance(false);}
}

1.新建数据(10行)会导致LazyHolder的加在吗?会初始化吗?
2.新建数组会导致LazyHolder的链接吗?
答案:
1.虚拟机必须知道(加载)有这个类,才能创建这个类的数组(容器),但是这个类并没有被使用到(没有达到初始化的条件),所以不会初始化。所以新建数组会加载元素类LazyHolder;不会初始化元素类
2.新建数组的时候并不是要使用这个类(只是定义了放这个类的容器),所以不会被链接,调用getInstance(false)的时候约等于告诉虚拟机,我要使用这个类了,你把这个类造好(链接),然后把static修饰的字符赋予变量(初始化)。

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

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

相关文章

大话成像公众号文章阅读学习(二)--- 下一代 AI-ISP会更好

系列文章目录 文章目录 系列文章目录前言一、AI-ISP1.1 定义与工作原理1.2 应用场景 二、展望总结 前言 这篇是 下一代 AI-ISP会更好 文章地址&#xff1a;https://mp.weixin.qq.com/s/N3YnkXF_stvP6k3jRTKCpQ 一、AI-ISP 1.1 定义与工作原理 定义&#xff1a;AI-ISP&#…

GEE:多面板同步缩放查看多源数据,并实现交互选点构建NDVI曲线

一. 目标 ①构建三个面板&#xff0c;分别显示不同来源数据&#xff1b; ②面板1显示哨兵数据面版2显示谷歌高清数据面板3实现用户任意交互选点&#xff0c;并以该点为中心构建正方形&#xff0c;随后生成该正方形的区域NDVI平均值长时序曲线&#xff1b; ③保证前两个面板可…

19.延迟队列优化

问题 前面所讲的延迟队列有一个不足之处&#xff0c;比如现在有一个需求需要延迟半个小时的消息&#xff0c;那么就只有添加一个新的队列。那就意味着&#xff0c;每新增一个不同时间需求&#xff0c;就会新创建一个队列。 解决方案 应该讲消息的时间不要跟队列绑定&#xf…

27、美国国家冰雪中心(NSIDC)海冰密集度月数据下载与处理

文章目录 一、前言二、数据下载三、使用Ponply查看数据结构四、代码一、前言 处理美国国家冰雪中心(NSIDC)的海冰密集度月度数据时,坐标转换是一个重要的步骤。NSIDC提供的数据通常采用极地球面坐标系,需要将其转换为常用的地理坐标系(如经纬度)以便进行分析和可视化。 坐…

python debug怎么用

1.打开pycharm&#xff0c;新建一个python程序&#xff0c;命名为excel.py。 2.直接贴出代码&#xff0c;如果是hello world就不存调试的问题了&#xff01; 3.介绍调试的菜单操作&#xff0c;在【菜单栏】选择【RUN】&#xff0c;下拉菜单里选择【debug excel.py】或者【Debug…

【C++】类与对象--初始化列表,类型转换,static,友元

文章目录 前言一、初始化列表1.1 初始化列表概述1.2 初始化列表注意事项初始化列表代码示例 二、类类型转换2.1 类类型转换2.2 代码示例 三.static成员3.1 静态成员变量3.2 代码示例 四.友元4.1友元概述4.2 友元特点4.3 友元代码示例 五.内部类5.1 内部类特点5.2 代码示例 六.匿…

掀桌子了!原来是咱们的大屏设计太酷,吓着前端开发老铁了

掀桌子了&#xff01;原来是咱们的大屏设计太酷&#xff0c;吓着前端开发老铁了 艾斯视觉观点认为&#xff1a;在软件开发的世界里&#xff0c;有时候创意和设计的火花会擦得特别亮&#xff0c;以至于让技术实现的伙伴们感到既兴奋又紧张。这不&#xff0c;我们的设计团队刚刚…

利用AI能力实现一个生成掘金、CSDN文章的总结并生成思维脑图

背景 为了快速了解文章重点&#xff01;&#xff01; 设计思路 1、根据文章链接、获取文章内容 2、编写 prompt 3、利用 markmap 显示思维导图 实现 获取文章内容 利用爬虫技术&#xff0c;简单利用 axios 获取链接内容&#xff0c;然后通过 cheerio 获取相关元素。 编码…

靶机Metasploitable2的安装

Metasploitable2是一款基于Ubuntu Linux的操作系统。Metasploitable2是一个虚拟机文件&#xff0c;从网上下载解压之后就可以直接使用&#xff0c;无需安装。该系统本身设计作为安全工具测试和演示常见漏洞攻击的靶机&#xff0c;所以它存在大量未打补丁漏洞&#xff0c;并且开…

C语言中的IO控制流

文章目录 一、什么是C语言中的IO控制流二、open函数 1.使用open函数创建文件2.使用使用open函数打开文件三、文件的权限四、文件的描述符五、read函数六、write函数七、lseek函数八、close函数 一、什么是C语言中的IO控制流 在linux系统中一切皆文件&#xff0c;C语言中的IO控…

13.2 MongoDB

13.2 MongoDB 1. 概述2. docker安装3. SpringBoot整合MongoDB3.1 依赖3.2 配置连接1. 基于`yml`配置2. 基于配置类配置3.3 启动项坑1坑23.4 新增业务1. 实体类映射2. 数据层3. 业务层4. 控制层5. 测试结果3.5 单条记录查询业务1. 数据层2. 业务层3. 控制层4. 断点测试3.6 分页查…

【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针

目录 常量指针和指向常量的指针有什么区别&#xff1f;1. 指向常量的指针&#xff08;Pointer to Constant&#xff09;声明方式&#xff1a;示例&#xff1a;解释&#xff1a; 2. 常量指针&#xff08;Constant Pointer&#xff09;声明方式&#xff1a;示例&#xff1a;解释&…

【es】elasticsearch 自定义排序-按关键字位置排序

一 背景 要求es查询的结果按关键字位置排序&#xff0c;位置越靠前优先级越高。 es版本7.14.0&#xff0c;项目是thrift&#xff0c;也可以平替springboot&#xff0c;使用easyes连接es。 二 easyes使用 配easyes按官方文档就差不多了 排序 | Easy-Es 主要的一个问题是easy…

Golang零基础入门课_20240726 课程笔记

视频课程 最近发现越来越多的公司在用Golang了&#xff0c;所以精心整理了一套视频教程给大家&#xff0c;这个只是其中的第一部&#xff0c;后续还会有很多。 视频已经录制完成&#xff0c;完整目录截图如下&#xff1a; 课程目录 01 第一个Go程序.mp402 定义变量.mp403 …

Leetcode—263. 丑数【简单】

2024每日刷题&#xff08;147&#xff09; Leetcode—263. 丑数 实现代码 class Solution { public:bool isUgly(int n) {if(n < 0) {return false;}for(const int prime: {2, 3, 5}) {while(n % prime 0) {n / prime;}}return n 1;} };运行结果 之后我会持续更新&#…

win11 备份mysql数据 卸载mysql 5 安装mysql 8详细教程(mysql的数据备份与卸载与安装)

如果是第一次安装mysql便可以直接看第三步 第一步&#xff1a;数据备份 我选择的是备份全部数据 以管理员身份运行cmd输入mysqldump -u root -p --all-databases --routines --triggers --single-transaction > C:\ProgramTools\MySql\backup_5.6.sql 其中&#xff1a;-u…

追问试面试系列:开篇

我们不管做任何事情&#xff0c;都是需要个理由&#xff0c;而不是盲目去做。 为什么写这个专栏&#xff1f; 就像我们被面试八股文时&#xff0c;市面上有很多面试八股文&#xff0c;随便一个八股文都是500&#xff0c;甚至1000面试题。诸多面试题&#xff0c;难道我们需要一…

前端和Postman调用同一个接口,拿到的数据不一样

1、表现 联调一个List接口&#xff0c;Postman自测得到的ID和前端调用得到的ID&#xff0c;结果不一样。前者结果&#xff1a; 后者结果&#xff1a; 同一份代码、同一个数据库&#xff0c;出现这种错误&#xff0c;大概率是类型转换时出问题了&#xff0c;但检查代码发现&…

对称性破缺与涌现——复杂科学与艺术之间的共鸣

中科院物理所 2022年08月14日 11:08 北京 以下文章来源于集智俱乐部 &#xff0c;作者十三维 导语 对复杂性的研究曾颠覆了科学原有的还原论范式&#xff0c;那么当复杂科学遇到艺术时会怎样&#xff1f;社会生物学家爱德华威尔逊&#xff08;E.O. Wilson&#xff09;曾说&am…

免费【2024】springboot 城市交通管理系统的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…