JVM(2)

JVM类加载

指的是java进程运行时,需要把.class文件从硬盘加载到内存,并进行一系列校验解析的过程.

核心: .class文件=>类对象;   硬盘=>内存.

类加载过程

在整个JVM的执行流程中,和程序员关系最密切的就是类加载的过程了,所以我们来看一下类加载的执行流程.

对于一个类,它的生命周期是这样的:

其中前五步是固定的顺序也是类的加载过程,其中中间的三步我们都属于连接,所以类加载有以下几个步骤: 

1.加载

2.连接

        a.验证

        b.准备

        c.解析

3.初始化

下面我们来看每个步骤的具体内容.

加载

定义:把硬盘上的.class文件,找到,打开文件,读取到文件指定内容.

 "加载"截断是整个"类加载"的过程中的一个阶段,它和类加载ClassLoading是不同的,一个是加载Loading另一个是类加载ClassLoading,所以不要把两者搞混了.

在加载Loading阶段,Java虚拟机需要完成以下事情:

(1)通过一个类的全限定名来获取此类的二进制字节流.

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

(3)在内存中生成一个代表这个类的java.lang.class对象,作为方法区这类的各种数据访问入口.

验证

验证是进行连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合 Java虚拟机 规范的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全.

验证选项:

文件格式验证

字节码验证

符号引用验证 

 准备

定义:给类对象申请内存空间.里面默认值全0(这个阶段中,类对象静态成员变量也是相当于0了).

比如此时有这么一行代码:

pubilc static int value = 123;

它是初始化value的int值为0,而非123. 

解析

定义:针对类中的字符串进行处理,解析阶段是Java虚拟机常量池内的符号替换为直接引用的过程,也就是初始化常量的过程.

 例如如下程序:

class Test {

        private String s = "hello";

}
.class文件内会包含这个hello.

上述代码中,很明确的知道,s变量里相当于保存了"hello",也就是字符串常量的地址.但是在文件中,不存在"地址"这样的概念. 地址是"内存"的地址.咱们是文件,是硬盘.

虽然没有地址,但是可以先存储一个类似于地址"偏移量"这样的概念.

接下来,要把.class文件加载到内存中.就会先把"hello"这个字符串加载到内存中.此时"hello"就有地址了. 接下来,s里面的值就可以替换成当前"hello"真实的地址了.

直接引用=>此处文件中填充给s的"hello"的偏移量就可以认为是"符号引用".

初始化

定义:针对类对象后续的初始化,还要执行代码块的逻辑,还会触发父类加载,初始化静态成员,执行静态代码块.

初始化阶段,Java虚拟机真正开始执行类中编写的Java程序代码,将主导权交给应用程序.初始化阶段就是执行类构造器方法的过程.

双亲委派模型

提到类加载机制,不得不提的概念就是"双亲委派模型".(描述了如何找到.class文件的策略).

站在Java虚拟机角度来看,只存在两种不同的类加载器(进行类加载的专门模块):一种是启动类加载器(BootstrapClassLoader),这个类加载器使用C++语言实现,是虚拟机的一部分;另外一种就是其它所有的类加载器,这些类加载器都由Java实现,独立存在于虚拟机外部,全部继承于抽象类java.lang.ClassLoader. 作用:给一个"全限定类名"(带有包名的类名),给定之后,找到对应的.class文件.

这里面,加载器存在"父子关系"(不是面向对象中的),而是类似于"二叉树",有parent指针指向.

Bootstrap ClassLoader负责查找标准库中的目录.

ExtensionClassLoader负责查找扩展库中的目录.

Application ClassLoader负责查找当前项目的代码目录. 

启动类加载器:加载JDK中lib目录中的Java核心类库,即JAVA_HOME/lib目录.扩展类加载器.加载lib/ext目录下的类.

应用程序类加载器:加载我们写的应用程序.

自定义类加载器:根据自己的需求定制类加载器 

什么是双亲委派模型 

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

具体流程:

1.从ApplicationClassLoader作为入口,先开始工作.

2.ApplicationClassLoader不会立即搜索自己负责的目录,要把搜索任务交给它的父亲

3.ExtensionClassLoader也不想立即搜索自己负责的目录,也把搜索目录交给自己的父亲.

4.BootstrapClassLoader也不想立即搜索,把搜索目录交给父亲.

5.BootstrapClassLoader发现自己没有父亲,才会真正搜索负责的目录(标准库目录).通过全限定类名,尝试在标准库目录中找符合要求的.class文件.

(1)如果找到了,接下来就直接进入到打开文件/读文件流程

(2)如果没找到,回到孩子这一辈的加载器中,尝试继续加载.

6.ExtensionClassLoader收到父亲交给他的任务后,自己自行搜索负责的目录.(当前项目目录/第三方目录)

(1)如果找到了,接下来进入后续的流程.

(2)如果没找到,也是回到孩子这一辈类加载器中继续加载.

7.ApplicationClassLoader收到父亲交给它的任务后,自己负责搜索的目录(当前项目目录/第三方目录)

(1)如果找到了,接下来就进入了后续流程

(2)如果未找到,也会回到这一辈的类加载器继续尝试加载.由于默认情况下ApplicationClassLoader没有孩子了,说明类加载的过程失败了,就出现ClassNotFoundException异常.

这样的过程,也与自己工作中问题处理逻辑一样:

当基层员工遇到一个问题时(自己拿不定主意),然后交给中层领导.,中层领导也拿不定,就会交给老板决定.老板如果能解决,就会直接解决,如果觉得没必要,就会交给中层领导,让它们自行解决,中层领导觉得自己能解决就会直接解决如果觉得没必要,就会交给员工解决.

这样的问题汇报是很重要的. 

按照上述的顺序,假定在代码中定义了一个java.lang.String这样的类,最终执行结果,自定义的类,不会被jvm加载.

上述的设定,也可以有效避免自己写的类,不小心和标准库中的类名重复,导致标准库的类名失效

上述一系列过程,也可以通过自己写一个类加载器打破原有过程,不过实现非常麻烦.

双亲委派模型的优点

1.避免重复加载类:比如A类和B类都有一个父类C类,那么A启动时就会将C类加载起来,那么在B类进行加载时就不需要重复加载C类了.

2.安全性:使用双亲委派模型也可以保证了Java核心的API不被篡改,如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个java.lang.Object类的话,那么程序运行的时候,系统就会出现多个不同的Object类,而有些Object类又是用户自己提供的因此安全性就不能得到保证了. 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【清理mysql数据库服务器二进制日志文件】

清理前后比对 清理前占用 86% : 清理后占用 29% : 排查占用磁盘较大的文件 检测磁盘空间占用 TOP 10 # 检测磁盘空间占用 TOP 10 $ sudo du -S /var/log/ | > sort -rn | # -n选项允许按数字排序。-r选项会先列出最大数字(逆序&#x…

Tomcat架构分析

Tomcat的核心组件 Tomcat将请求器和处理器分离,使用多种请求器支持不同的网络协议,而处理器只有一个。从而网络协议和容器解耦。 Tomcat的容器 Host:Tomcat提供多个域名的服务,其将每个域名都视为一个虚拟的主机,在…

git忽略某些文件(夹)更改说明

概述 在项目中,常有需要忽略的文件、文件夹提交到代码仓库中,在此做个笔录。 一、在项目根目录内新建文本文件,并重命名为.gitignore,该文件语法如下 # 以#开始的行,被视为注释. # 忽略掉所有文件名是 a.txt的文件. a.txt # 忽略所有生成的 java文件, *.java # a.j…

java演唱会网上订票购票系统springboot+vue

随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的交换和信息流通显得特别重要。因此,开发合适的基于springboot的演唱会购票系统的设计与实现成为企业必然要走…

【MySQL】内置函数 -- 详解

一、日期函数 日期:年月日时间:时分秒 1、获得年月日 2、获得时分秒 3、获得时间戳 4、在日期的基础上加日期 5、在日期的基础上减去时间 6、计算两个日期之间相差多少天 7、获得当前时间 ⚪练习 (1)记录生日 (2&…

Qt中关于信号与槽函数的思考

信号与槽函数的思考 以pushbutton控件为例,在主界面上放置一个pushbutton控件,点击右键选择关联槽函数,关联一个click函数,如下图所示: 在该函数中,实现了一个点击pushbutton按钮后,弹出一个窗…

德人合科技 | 天锐绿盾终端安全管理系统

德人合科技提到的“天锐绿盾终端安全管理系统”是一款专业的信息安全防泄密软件。这款软件基于核心驱动层,为企业提供信息化防泄密一体化方案。 www.drhchina.com 其主要特点包括: 数据防泄密管理:天锐绿盾终端安全管理系统能够确保数据在创…

淘宝商品数据爬取商品信息采集数据分析API接口详细步骤展示(含测试链接)

01 数据采集 数据采集是数据可视化分析的第一步,也是最基础的一步,数据采集的数量和质量越高,后面分析的准确的也就越高,我们来看一下淘宝网的数据该如何爬取。点此获取淘宝API测试key&密钥 淘宝网站是一个动态加载的网站&a…

pytorch 图像的卷积操作

目录 1.卷积核基本参数说明 2.卷积相关操作说明 3.卷积操作示例 1.卷积核基本参数说明 pytorch进行图像卷积操作之前,需要把图像素格式进行分离,比如一个图像为rgb格式,把R,G,B取出来作为一个ndarray,前文讲过&#…

基于串流技术的p2p共享桌面共享方案

研究远控有一定时间了,但真正落地运用的不多,所以也不太上心,平时也只是自己diy玩玩,远程共享看看电视剧。 最近生成式ai大火,直接带动了gpu应用的相关场景,相关场景,但gpu卡又贵,对…

TP6上传图片到OSS(记录贴)

1&#xff0c;先安装&#xff0c;我使用composer安装 在项目的根目录运行composer require aliyuncs/oss-sdk-php 2,安装成功以后vendor目录下可以看到如图&#xff1a; 3&#xff0c;上传图片代码如下&#xff1a; <?php namespace app\controller;use app\BaseControll…

vm虚拟机的下载与安装(更新时间24/2/28)

首先进入vm官网点击跳转 进入products 进入Workstation Pro 点击DOWNLOAD TRIAL 点击DOWNLOAD NOW 到这里只需要等待下载完成就行了 安装就是正常软件程序的安装方法&#xff0c;除了自定义一下安装位置&#xff0c;其他的直接确定 许可证密钥 在网络上有很多随便一搜…

基于springboot+vue的可盈保险合同管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

2024年 前端JavaScript Web APIs 第一天 笔记

1.1 -声明变量const优先 1.2 -DOM树和DOM对象 1.3 -获取DOIM元素 1.4 -DOM修改元素内容以及年会抽奖 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content&quo…

vue中 input disable后无法触发点击事件

问题&#xff1a;input标签为disabled后&#xff0c;点击事项无效&#xff1b;当点击文字**“请选择”**时无法触发点击事件&#xff0c;其父标签的其余位置均可触发 解决&#xff1a;只需要在input标签中添加 style“pointer-events:none” 即可 pointer-events: none 作用是…

【Linux】协程简介

【Linux】协程简介 一、什么是协程&#xff1f;简介优点 二、为什么使用协程&#xff1f;三、协程的种类1、对称协程2、非对称协程 四、协程栈1、静态栈2、分段栈3、共享栈4、虚拟内存栈 五、协程调度1、栈式调度2、星切调度3、环切调度 六、常见协程库参考文献 一、什么是协程…

Vue+Flask电商后台管理系统

在这个项目中&#xff0c;我们将结合Vue.js前端框架和python后端框架Flask&#xff0c;打造一个功能强大、易于使用的电商后台管理系统 项目演示视频&#xff1a; VueFlask项目 目录 前端环境&#xff08;Vue.js&#xff09;&#xff1a; 后端环境&#xff08;python-Flask&…

基于RISC-V架构的通信DSP的设计以及在5G RedCap基带中的应用(五)-基于RISC-V的RedCap DSP在5G基带中的应用

4 基于RISC-V的RedCap DSP在5G基带中的应用 4.1 基带处理器的关键任务和性能需求 基带处理器是移动通信设备中的关键部件&#xff0c;负责处理无线信号&#xff0c;包括信号的接收、发送和处理。在5G通信系统中&#xff0c;基带处理器的关键任务和性能需求包括以下几个方面&a…

【DAY05 软考中级备考笔记】线性表,栈和队列,串数组矩阵和广义表

线性表&#xff0c;栈和队列&#xff0c;串数组矩阵和广义表 2月28日 – 天气&#xff1a;阴转晴 时隔好几天没有学习了&#xff0c;今天补上。明天发工资&#xff0c;开心&#x1f604; 1. 线性表 1.1 线性表的结构 首先线性表的结构分为物理结构和逻辑结构 物理结构按照实…

基于Redo log Undo log的MySQL的崩溃恢复

基于Redo log & Undo log的MySQL的崩溃恢复 Redo log Undo log Redo log 重做日志,记录,修改过的数据 Undo log 回滚日志,记录修改之前的数据 两个我不做详细的介绍了,redo log就是记录哪些地方被修改了 undo log是记录修改之前我们的数据长什么样 更新流程 我们来捋一…