4-JVM类加载

news2024/10/6 18:31:33

目录

1.类加载过程

1.1.加载(去车站)

1.2.验证(过安检)

1.3.准备(候车)

1.4.解析(检票)

1.5.初始化(上车)

2.双亲委派模型

2.1.什么是双亲委派模型?

2.2.双亲委派模型的优点

3.破坏双亲委派模型


1.类加载过程

在整个 JVM 执行的流程中,和程序员关系最密切的就是类加载的过程了。

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

其中前 5 步是固定的顺序并且也是类加载的过程,其中中间的 3 步都属于连接,所以对于类加载来说总共分为以下几个步骤:

  • 加载
  • 连接
  1. 验证
  2. 准备
  3. 解析
  • 初始化

1.1.加载(去车站)

“加载”(Loading)阶段是整个“类加载”(Class Loading)过程中的一个阶段,它和类加载 Class Loading 是不同的,一个是加载 Loading,另一个是类加载 Class Loading,所以不要把二者搞混了。

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

  1. 通过一个类的全限定名(完整的包名+类名)来获取定义此类的二进制字节流。
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

1.2.验证(过安检)

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

验证选项:

  • 文件格式验证
  • 字节码验证
  • 符号引用(相当于指针:内存地址)验证
  • ...

1.3.准备(候车)

准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段。

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

public static int value = 123;

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

1.4.解析(检票)

解析阶段是 Java 虚拟机将常量池内的符号引用(相当于一个符号,这个符号还没有在内存中生效)替换为直接引用(内存中的对象)的过程,也就是初始化常量的过程。

1.5.初始化(上车)

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

2.双亲委派模型

提到类加载机制,不得不提的一个概念就是“双亲委派模型”。

站在 Java 虚拟机的角度来看,只存在两种不同的类加载器:

  • 一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用 C++ 语言实现,是虚拟机自身的一部分;
  • 另外一种就是其他所有的类加载器,这些类加载器都由Java语言实现,独立存在于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader。

站在 Java 开发人员的角度来看,类加载器就应当划分得更细致一 些。自 JDK 1.2 以来,Java 一直保持着三层类加载器、双亲委派的类加载架构器。

2.1.什么是双亲委派模型?

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

所有的API都是来自rt.jar包,

  • 启动类加载器:加载 JDK 中 lib 目录中 Java 的核心类库,即 $JAVA_HOME/lib 目录。所有的 API 都是来自 rt.jar 包。
  • 扩展类加载器:加载 lib/ext 目录下的类,都是扩展 jar 包。
  • 应用程序类加载器:加载我们写的应用程序。
  • 自定义类加载器:根据自己的需求定制类加载器。 

2.2.双亲委派模型的优点

  1. 避免重复加载类:比如 A 类和 B 类都有一个父类 C 类,那么当 A 启动时就会将 C 类加载起来,那么在 B 类进行加载时就不需要再重复加载 C 类了。
  2. 安全性:使用双亲委派模型也可以保证了 Java 的核心 API 不被篡改,如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类,而有些 Object 类又是用户自己提供的,因此安全性就不能得到保证了。

3.破坏双亲委派模型

双亲委派模型虽然有其优点,但在某些情况下也存在一定的问题/缺点:比如①Java 中 SPI(Service Provider Interface,服务提供接口)机制中的 JDBC 实现;②Tomcat 容器加载。

小知识:SPI 全称 Service Provider Interface,是 Java 提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI 的作用就是为这些被扩展的 API 寻找服务实现。

JDBC 的 Driver 接口定义在 JDK 中,其实现由各个数据库的服务商来提供,比如 MySQL 驱动包。先来看下 JDBC 的核心使用代码:

public class JdbcTest {
   public static void main(String[] args) {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "awakeyo");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println(connection.getClass().getClassLoader());
        System.out.println(Thread.currentThread().getContextClassLoader());
        System.out.println(Connection.class.getClassLoader());
   }
}

然后进入 DriverManager 的源码类就会发现它是存在系统的 rt.jar 中的:

由双亲委派模型的加载流程可知 rt.jar 是由顶级父类 Bootstrap ClassLoader 加载的:

而当进入它的 getConnection 源码是却发现,它在调用具体的类实现时,使用的是子类加载器(线程上下文加载器 Thread.currentThread().getContextClassLoader )来加载具体的数据库数据库包 (如 mysql 的 jar 包),源码如下:

@CallerSensitive
public static Connection getConnection(String url, java.util.Properties info) throws SQLException {
    return (getConnection(url, info, Reflection.getCallerClass()));
}

private static Connection getConnection (String url, java.util.Properties info, Class<?> caller) throws SQLException {
    ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
    synchronized(DriverManager.class) {
        // synchronize loading of the correct classloader.
        if (callerCL == null) {
            //获取线程上下为类加载器
            callerCL = Thread.currentThread().getContextClassLoader();
        }
    }
    if(url == null) {
        throw new SQLException("The url cannot be null", "08001");
    }
    println("DriverManager.getConnection(\"" + url + "\")");
    SQLException reason = null;
    for(DriverInfo aDriver : registeredDrivers) {
        // isDriverAllowed 对于 mysql 连接 jar 进行加载
        if(isDriverAllowed(aDriver.driver, callerCL)) {
            try {
                println("trying" + aDriver.driver.getClass().getName());
                Connection con = aDriver.driver.connect(url, info);
                if (con != null) {
                    // Success!
                    println("getConnection returning " + aDriver.driver.getClass().getName());
                    return (con);
                }
            } catch (SQLException ex) {
                if (reason == null) {
                    reason = ex;
                }
            }
        } else {
            println("   skipping: " + aDriver.getClass().getName());
        }
    }
    if (reason != null)   {
        println("getConnection failed: " + reason);
        throw reason;
    }
    println("getConnection: no suitable driver found for "+ url);
    throw new SQLException("No suitable driver found for "+ url, "08001");
}

这样一来就破坏了双亲委派模型,因为 DriverManager 位于 rt.jar 包,由 BootStrap 类加载器加载, 而其 Driver 接口的实现类是位于服务商提供的 jar 包中,是由子类加载器(线程上下文加载器 Thread.currentThread().getContextClassLoader)来加载的,这样就破坏了双亲委派模型了(双亲委派模型讲的是所有类都应该交给父类来加载,但 JDBC 显然并不能这样实现)。

它的交互流程图如下所示:

 

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

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

相关文章

首次曝光!乔布斯这些从未公开的照片,揭露乔布斯的另一面

昨个&#xff0c;大神在群里分享了一本关于乔布斯的书籍。 这本书收录了他的照片、电子邮件、演讲稿和访谈&#xff0c;很多私人的邮件和访谈是第一次看到。 书中用乔布斯自己的视角&#xff0c;记录了他一生的轨迹&#xff0c;包括他的童年&#xff0c;创立、离开、重归苹果的…

【Matter】如何在Linux平台下测试Matter应用级通信(虚拟设备)

如何在Linux平台下测试Matter应用级通信(虚拟设备) 准备工作 1. 递归克隆Matter仓库 执行如下命令&#xff1a; git clone --recurse-submodules gitgithub.com:project-chip/connectedhomeip.git如果克隆过程中发生报错&#xff0c;请执行如下命令来同步子模块&#xff1a;…

【好书精读】网络是怎样连接的 之 委托协议栈发送消息

&#xff08;该图由AI制作 学习AI绘图 联系我&#xff09; 目录 数据收发操作概览 创建套接字阶段 连接阶段&#xff1a;把管道接上去 通信阶段&#xff1a;传递消息 断开阶段&#xff1a;收发数据结束 数据收发操作概览 知道了 IP 地址之后 &#xff0c; 就可以委托操…

Spring Boot高阶篇笔记

一、Spring Boot整合Redis缓存 JSR-107、Spring缓存抽象、整合Redis 1、JSR107 Java Caching定义了5个核心接口&#xff0c;分别是CachingProvider, CacheManager, Cache, Entry 和 Expiry。 • CachingProvider定义了创建、配置、获取、管理和控制多个CacheManager。一个应…

打造Top级期货交易系统!成为投资高手!

交易系统在期货市场中得到广泛的应用&#xff0c;技术分析是期货交易系统的重要组成部分之一。技术分析是依靠市场数据来预测未来期货行情的一种方法&#xff0c;通过对期货历史市场信息进行形态分析和统计计算等手段&#xff0c;获取市场行情的走向&#xff0c;为后续的期货交…

初识MFC第一天

文章目录 前言一、初识MFC二、初始相关API附录 前言 刚开始进入Win32开发时&#xff0c;会发现一些变量类型似乎在C语言中未曾见过。其实这些变量类型或是与C/C已有的数据类型相近的&#xff0c;是通过C语言的原始类型重新定义而成的。引入这些数据类型的主要目的是为了便于程…

2023届网课生就业难:挑战与策略探析

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

One-Class SVM详解

简介 One-Class SVM&#xff08;Support Vector Machine&#xff09;是一种无监督学习算法&#xff0c;用于异常检测和离群点检测。它的目标是通过仅使用正常数据来建模&#xff0c;识别出与正常模式不同的异常数据点。 One-Class SVM的工作原理如下&#xff1a; 数据映射&a…

潮玩盲盒APP系统开发

盲盒抽奖App软件界面应该包括以下几个部分&#xff1a; 首页&#xff1a;首页需要展示正在进行的抽奖活动、热门盲盒商品和刚刚开奖的中奖名单&#xff0c;让用户快速了解当前的热门活动和优惠。 抽奖详情页&#xff1a;抽奖详情页需要展示抽奖主题、奖品图片、中奖规则…

高频前端面试题汇总之计算机网络篇

一、HTTP协议 1. GET和POST的请求的区别 Post 和 Get 是 HTTP 请求的两种方法&#xff0c;其区别如下&#xff1a; 应用场景&#xff1a; GET 请求是一个幂等的请求&#xff0c;一般 Get 请求用于对服务器资源不会产生影响的场景&#xff0c;比如说请求一个网页的资源。而 P…

SAX解析XML返回对应格式的Map对象

前言 最近有一个解析大型xml的需求&#xff0c;xml大小7M&#xff0c;其中xml结构非常复杂&#xff0c;元素各种嵌套 不乏有元素下对象&#xff0c;元素下集合&#xff0c;集合下对象&#xff0c;集合下集合&#xff0c;兄弟节点&#xff0c;元素下对象下集合&#xff0c;同一元…

数字时代,你想成为一只“弱鸡”,还是一个“超级个体”?

电话延伸了人类的耳朵&#xff0c;屏幕延伸了人类的眼睛&#xff0c;汽车这样的交通工具延伸了人类的腿脚&#xff0c;人类的生存能力开始变得和技术相关&#xff0c;而这个趋势仍在加剧。 如今&#xff0c;Web3延伸了人的综合体验&#xff0c;AI延伸了人类的大脑&#xff0c;它…

MySQL(视图、存储过程与函数、流程控制、触发器)

第一章 视图 1 什么是视图 为了提高复杂的SQL语句的复用性和表的操作的安全性 &#xff0c;MySQL数据库管理系统提高了视图特性&#xff0c;所谓视图&#xff0c;本质上是一种虚拟表&#xff0c;其内容与真实的表相似&#xff0c;包含一系列带有名称的列和行数据。但是视图并…

2023年前端面试汇总 - JavaScript

1. 数据类型 1.1. JavaScript有哪些数据类型&#xff0c;它们的区别&#xff1f; JavaScript共有八种数据类型&#xff0c;分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。 其中 Symbol 和 BigInt 是ES6 中新增的数据类型&#xff1a; Symbol …

避开这12个压测误区保证有效压测

压测本质上其实就是经验的问题&#xff0c;至于技术我认为现在都是配套了&#xff0c;也有人配套的东西也搞不清&#xff0c;那还是经验的问题。提醒下&#xff0c;这篇对野路子玩压测的人蛮有用的。 一、压测的误区 首先讲压测误区&#xff0c;每个误区我会简单的总结下&…

作为超级自动化的重要先驱,流程挖掘正在成为组织运营标配

正在成为组织运营标配的流程挖掘&#xff0c;到底有哪些商业价值&#xff1f; 作为超级自动化的重要先驱&#xff0c;流程挖掘正在成为组织运营标配 文/王吉伟 AIGC正在影响越来越多的行业&#xff0c;流程挖掘领域亦不例外。 Mindzie首先宣布集成生成式AI&#xff0c;使用户…

带你详细了解Redis事务锁机制-加实列演示-上

Redis_事务_锁机制_秒杀 Redis 的事务是什么? 1、Redis 事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化、按顺序地执行 2、事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断 3、Redis 事务的主要作用就是串联多个命令防止别的命令…

怎么学习和提升前端开发的能力? - 易智编译EaseEditing

要学习和提升前端开发的能力&#xff0c;您可以按照以下步骤进行&#xff1a; 掌握基础知识&#xff1a; 了解HTML、CSS和JavaScript的基本概念和语法。学习HTML用于创建网页结构&#xff0c;CSS用于样式设计和布局&#xff0c;JavaScript用于交互和动态效果。 学习框架和库&…

探讨太阳能热水器的安全隐患和雷电防护措施

太阳能热水器是指利用太阳光加热原理来获得热水的装置。随着科学技术的发展&#xff0c;太阳能热水器因其新颖、环保、节能且方便而深受消费者的喜爱&#xff0c;安装数量逐年增加。我国太阳能资源丰富&#xff0c;尤其是在广袤的西部中小城镇、农村地区&#xff0c;家家户户几…

NSSA实验和配置命令

1)拓扑 需求 2)需求&#xff1a;PC2和PC5互通 配置思路和配置命令 3&#xff09;配置思路&#xff1a; 第一步&#xff1a;先让R1能够和PC5互通&#xff0c;要先配置静态路由 [R1] ip route-static 192.168.4.0 24 192.168.18.8 第二步&#xff1a;在R8上写去往PC1/PC2的路…