【JVM】类加载子系统——自问自答

news2024/10/5 16:29:20

1、类加载的过程:

java的类加载过程,是把字节码文件(.class file) 转换到JVM中运行时数据区内的过程。

类加载的过程由 类加载器子系统完成(Class Loader).

字节码文件可以像我们日常开发时在特定文件夹路径下的jar包里,也可以从网络中获取,也可以来自数据库,等等。

  • 类加载器子系统负责从文件系统或网络中加载class文件,class文件在文件开头有特定的标识符(CAFE BABE)
  • ClassLoader 只负责class文件的加载,至于它是否可以运行,则由ExecutionEngine决定。
  • 加载后的类信息 存放在方法区。
  • 综上所述 .class--->JVM--->元数据模板。类加载器就是这个过程的搬运工。

1.1  加载过程拆解

加载 ---链接(验证、准备、解析)-----初始化

1、Loading   (其实就是ClassLoader里loadClass的执行细节)

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

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

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

2、Linking

        1) 验证verify

      目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性不会危害虚拟机自身安全。
    主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。

        2)准备Prepare :

类变量分配内存并且设置该类变量的默认初始值,即零值。

这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化;


这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分
配到Java堆中。

静态变量的第一次赋值。

3)解析(Resolve) :


将常量池内的符号引用转换为直接引用的过程。
 

3、initialization

初始化阶段就是执行类构造器方法<clinit>() 的过程

此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静
态代码块中的语句合并而来。

构造器方法中指令按语句在源文件中出现的顺序执行。

<clinit>()不同于类的构造器。

若该类具有父类,JVM会保证子类的<clinit>() 执行前,父类的<clinit>()已经执行完毕。
虚拟机必须保证一个类的<clinit>() 方法在多线程下被同步加锁。

构造器是虚拟机视角下的<init>())

2、加载器的分类

JVM支持两种类型的类加载器,分别为引导类加载器 (BootstrapclassLoader) 自定义类加载器(User-Defined ClassLoader)

从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范却没有这么定义,而是将所有派生于抽象类classLoader的类加载器都划分为自定义类加载器。
无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个,如下所示:

特别强调,这四者并不是继承关系,而是包含关系。ClassLoader里有个final ClassLoader属性 parent。在进行双亲委派的时候,会用到。

1、关于ClassLoader

sun.misc.Launcher它是一个java虚拟机的入口应用。

AppClassLoader 和ExClassLoder 都是它的内部类

2、各类加载器

虚拟机自带的加载器
  • 启动类加载器引导类加载器,Bootstrap classLoader
  •    这个类加载使用c/c++语言实现的,嵌套在JVM内部。
  •    它用来加载Java的核心库 (JAVA_HOME/re/lib/rt.jar、resources.jar或sun.boot.class.path路径下     的内容),用于提供JVM自身需要的类
  •   并不继承自java.lang.classLoader,没有父加载器
  •   加载扩展类和应用程序类加载器,并指定为他们的父类加载器
  •  出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类

  • 扩展类加载器 (Extension ClassLoader)
  • Java语言编与,由sun.misc.LauncherSExtclassLoader实现
  • 派生于classLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录 (扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

  • 应用程序类加载器(系统类加载器,AppclassLoader)
  • java语言编写,由sun.misc.LauncherSAppclassLoader实现
  • 派生于classLoader类
  • 父类加载器为扩展类加载器
  • 它负责加载环境变量classpath或系统属性 java.class.path 指定路径下的类库
  • 该类加载是程序即默认的类加载器,一般来说,Java应用的类都是由它来完成加载
  • 通过classLoader#qetSystemClassLoader()方法可以获取到该类加载器

3、双亲委派

Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理它是一种任务委派模式。

工作原理
1)如果一个来加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
2)如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器;

3)如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自已去加载,这就是双亲委派模式。

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

关于SPI的打破双亲委派的

双亲委派的优势:


避免类的重复加载

保护程序安全,防止核心API被随意篡改

4、沙箱安全机制

5、补充:

两个类是否相同的判定依据

  • 在JVM中表示两个class对象是否为同一个类存在两个必要条件:
  • 类的完整类名必须一致,包括包名。
  •  加载这个类的classLoader(指classLoader实例对象)必须相同。

JVM必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的,那么JVM会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中,当解析一个类型到另一个类型的引用的时候,JVM需要保证这两个来型的类加载器是相同的。

6、类的主动使用和被动使用

主动使用,又分为七种情况:

  • 创建类的实例
  • 访问某个类或接口的静态变量,或者对该静态变量赋值
  • 调用类的静态方法
  • 反射(比如: Class.forName(“com.alex.Test"))初始化一个类的子类
  • Java虚拟机启动时被标明为启动类的类
  • JDK 7 开始提供的动态语言支持:
  • java.lang.invoke.MethodHandle实例的解析结果REF getStatic、REF putStatic、REF invokeStatic句柄对应的类没有初始化,则初始化


除了以上七种情况,其他使用Java类的方式都被看作是对类的被动使用都不会导致类的初始化 (前面说了,类的初始化 是要执行<clint>

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

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

相关文章

【RocketMQ】(七)事务实现原理

RocketMQ事务的使用场景 单体架构下的事务 在单体系统的开发过程中&#xff0c;假如某个场景下需要对数据库的多张表进行操作&#xff0c;为了保证数据的一致性&#xff0c;一般会使用事务&#xff0c;将所有的操作全部提交或者在出错的时候全部回滚。以创建订单为例&#xf…

6.5 图的遍历

前言&#xff1a; 主要内容&#xff1a; 这段文字描述的是图的遍历。图的遍历与树的遍历有些相似&#xff0c;都是从某个点开始&#xff0c;按照一定的规则遍历其他的点&#xff0c;但是图的遍历更加复杂&#xff0c;因为图中存在循环和回路&#xff0c;这意味着可能会多次访…

JavaWeb开发-09-MyBatis

官网&#xff1a;https://mybatis.org/mybatis-3/zh/index.html 一.Mybatis入门 1.快速入门 2.JDBC介绍 3.数据库连接池 官方地址&#xff1a;https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter 4.lombok 二.Mybatis基础增删改查 1.准备 2.删除 3.新增…

AT24C02芯片

AT24C02简介&#xff1a; AT24C01/02/04/08/16...是一个 1K/2K/4K/8K/16K 位串行 CMOS内部有9个字节&#xff1b; 该器件通过 I2C 总线接口进行 操作&#xff0c;它有一个专门的写保护功能&#xff1b; 基于51 他有这个芯片操作 时序&#xff1a; AT24C02软件编程&#xff1a; …

darknet yolov3 模型训练步骤整理

1. 把需要训练的图片拷贝到 D:\模型训练\darknet-master\build\darknet\x64\data\VOCdevkit\VOC2012\JPEGImage 2. 执行imageName.py 文件&#xff0c;重命名JPEGImage下的图片。 D:\模型训练\darknet-master\build\darknet\x64\data\VOCdevkit\VOC2012\imageName.py 3. 用…

Termius 8 for Mac(多协议服务器连接软件)

Termius是一款远程访问和管理工具&#xff0c;旨在帮助用户轻松地远程连接到各种服务器和设备。它适用于多种操作系统&#xff0c;包括Windows、macOS、Linux和移动设备。 该软件提供了一个直观的界面&#xff0c;使用户可以通过SSH、Telnet和Mosh等协议连接到远程设备。它还支…

微表情识别API + c++并发服务器系统

微表情识别API系统 该项目只开源前后端程序&#xff0c;模型不开源 地址&#xff1a;https://github.com/lin-lai/-API- 更新功能 4.1版本 改用epoll实现IO多路复用并发服务器去除标志位设定—正在考虑用协议实现 项目介绍 本项目用于检测并识别视频中人脸的微表情 目标任…

【插件】页面引导库driver.js:

文章目录 一、效果图:二、实现思路:三、实现代码:【1】Driver.js 的技术特性【2】安装依赖【3】代码实现【4】 配置相关参数 一、效果图: 二、实现思路: 【官网】https://driverjs.com/docs/installation 【npm】https://www.npmjs.com/package/driver.js 【案例】改造driver.j…

用Python在XML和Excel表格之间实现互转

XML是一种超文本标记语言和文件格式&#xff0c;具有可自定义标签&#xff0c;易于扩展&#xff0c;便于编辑&#xff0c;传输便捷等优点。XML已成为应用数据交换的常用方式。虽然XML格式易于传输和开发者操作&#xff0c;但对于普通用户来说&#xff0c;数据以xls或xlsx的形式…

二维穿墙雷达CW112 的 优势

TFN CW112加固型二维定位穿墙雷达是一款综合UWB雷达和生物医学工程技术研制而成的人体目标探测装备。该产品可穿透建筑墙体等障碍物&#xff0c;实时获取其后方人体目标位置及数量等信息&#xff0c;具有穿透性强、轻质便携、可双手操控等特点&#xff0c;广泛应用于反恐处突、…

vue+element项目创建步骤

一、创建vue项目步骤 要创建一个Vue Element UI的项目&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1.确保你已经安装了Node.js和npm&#xff08;Node.js的包管理器&#xff09;。你可以在命令行中运行以下命令来检查它们是否已经安装&#xff1a; node -vnpm -v2.使…

视频超过1g怎么压缩?分享简单的视频压缩方法

随着科技的发展&#xff0c;视频已经成为了我们日常生活中不可或缺的一部分。然而&#xff0c;有时候我们会遇到视频文件过大&#xff0c;无法顺利传输或存储的问题。那么&#xff0c;如何解决视频超过1g压缩的问题呢&#xff1f; #长假读书清单# 首先我们可以借助专业的压缩…

华为云云耀云服务器L实例评测|运行python脚本

目录 一、往期回顾二、华为云云耀云服务器L实例使用流程1、账号注册2、购买并配置云耀云服务器L实例3、登录并使用云耀云服务器L实例 三、为什么Python越来越火&#xff1f;四、使用宝塔运行Python脚本1、下载Python项目管理器2、上传项目到服务器3、添加项目4、安装requests启…

一文读懂Llama 2(从原理到实战)

简介 Llama 2&#xff0c;是Meta AI正式发布的最新一代开源大模型。 Llama 2训练所用的token翻了一倍至2万亿&#xff0c;同时对于使用大模型最重要的上下文长度限制&#xff0c;Llama 2也翻了一倍。Llama 2包含了70亿、130亿和700亿参数的模型。Meta宣布将与微软Azure进行合…

便携式水质采样设备助力毒情监测

便携式水质采样设备助力毒情监测 污水涉毒采样检测工作是运用科技手段准确评估监测辖区内毒情形势的重要手段。期间&#xff0c;民警详细了解了生活和工业污水的处理、排放以及服务范围、人口数量等情况&#xff0c;并就污水涉毒采样检测工作达成共识。随后&#xff0c;民警严格…

【车载开发系列】ECU Application Software程序刷新步骤

【车载开发系列】ECU Application Software程序刷新步骤 ECU Application Software程序刷新步骤 【车载开发系列】ECU Application Software程序刷新步骤一. Boot Software&#xff08;引导软件&#xff09;1&#xff09;boot manager&#xff08;启动管理器&#xff09;2&…

Flink1.12.7 Standalone版本安装

官网下载版本&#xff1a;https://archive.apache.org/dist/flink/flink-1.12.7/flink-1.12.7-bin-scala_2.12.tgz 可以从首页找到Downloads | Apache Flink&#xff0c;一直往下拉 安装&#xff1a;下载后直接解压即可 添加全局参数&#xff1a; #vi /etc/profile FLINK_HO…

云服务器免费体检

三丰云提供了免费云服务器与免费虚拟主机服务&#xff0c; 个人学习、搭建个人网站或者微信小程序调试等可以申请一台。 免费申请网址为&#xff1a; https://www.sanfengyun.com/ 还是挺方便的&#xff0c;大家可以体验体验。

【校招VIP】前端操作系统之I/O调度算法

考点介绍 I/O 调度算法在各个进程竞争磁盘I/O的时候担当了裁判的角色。他要求请求的次序和时机做最优化的处理&#xff0c;以求得尽可能最好的整体I/O性能。 前端操作系统之I/O调度算法-相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点题目 1. 某文件占10个…