类加载器和双亲委派模型面试总结

news2024/12/23 11:41:35

类的生命周期和类加载的过程

在了解类加载器之前,我们先来了解一下一个类的生命周期和类加载的过程。

一个类完整的生命周期包括 加载、验证、准备、解析、初始化、使用和卸载,一共7个阶段。

类加载过程包括,加载连接初始化,一共3个阶段,其中连接阶段又包含验证准备解析3个阶段。

如果想了解类加载过程的详细内容,请移步观看我的另一篇博客——JVM面试题详解系列——类加载过程详解

在这里插入图片描述

类加载器总结

从Java虚拟机角度,只存在以下两种类加载器:

  • 启动类加载器(Bootstrap ClassLoader),使用c++实现,是虚拟机的一部分。
  • 其他所有类加载器,使用Java实现,独立于虚拟机,且全部继承自抽象类 java.lang.ClassLoader。

从Java开发人员的角度,类加载器可以划分的更细致一些:

  • 启动类加载器(Bootstrap ClassLoader):是JVM内置的类加载器,负责加载JVM自身需要的类和资源,包括Java核心类库(如rt.jar、resources.jar等)。Bootstrap ClassLoader是使用C++语言实现的,因此无法在Java代码中直接使用,用户在编写自定义类加载器时,如果需要把加载请求委派给启动类加载器,直接使用 null 代替即可。

  • 扩展类加载器(Extension ClassLoader):用于加载Java扩展类库(如jre/lib/ext目录下的jar包)。由Java编写,是由sun.misc.Launcher$ExtClassLoader实现的,开发者可以直接使用扩展类加载器。

  • 系统类加载器(System ClassLoader):也称为应用程序类加载器(Application ClassLoader),用于加载应用程序的类文件,即classpath下的类文件。由Java编写,是由sun.misc.Launcher$AppClassLoader实现的。

Java类加载器的作用主要有以下几个方面

  1. 加载类文件:类加载器负责将类文件加载到JVM中,以便JVM能够执行其中的Java代码。

  2. 提供命名空间:类加载器为每个类提供了一个独立的命名空间,不同的类加载器加载的同名类是相互独立的,避免了类名冲突的问题。

  3. 实现类的隔离:类加载器可以实现类的隔离,即同一个JVM中的不同的类加载器加载的类互不干扰,可以避免由于类名冲突或版本不一致等问题导致的程序崩溃。

  4. 实现动态加载:类加载器可以在程序运行期间动态加载类文件,使得程序可以在运行时根据需要加载不同的类。

提高程序安全性:类加载器可以通过自定义实现,实现类文件的加密和解密,提高程序的安全性。
总之,Java类加载器是JVM中非常重要的组成部分,通过实现类的动态加载、隔离和命名空间等功能,为Java应用程序提供了良好的灵活性和安全性。

双亲委派模型

双亲委派模型介绍

每一个类都有一个对应它的类加载器。系统中的 ClassLoader 在协同工作的时候会默认使用 双亲委派模型

如果一个类加载器收到了类加载的请求,系统会首先判断当前类是否已经被加载过,已经被加载的类会直接返回,否则才会尝试加载。加载的时候,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

在这里插入图片描述

每个类加载器都有一个父类加载器

每个类加载器都有一个父类加载器,如果一个类加载器的父类加载器为 null,并不代表这个类加载器没有父类加载器,而是这个类的父类加载器是BootstrapClassLoader 。

双亲委派模型实现源码分析

双亲委派模型的实现代码非常简单,逻辑非常清晰,都集中在 java.lang.ClassLoader 的 loadClass() 中,相关代码如下所示。

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,检查类是否已经被加载
            Class<?> c = findLoadedClass(name);
            if (c == null) { //类没有被加载,首先会将请求委派给父类加载器完成
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);  //父类加载器不为空,调用父类加载器的loadClass()方法
                    } else {  
                        c = findBootstrapClassOrNull(name); //父类加载器为空,使用启动类加载器 BootStrapClassLoader 加载。
                    }
                } 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;
        }
    }

双亲委派模型的好处

  • 避免类的重复加载
  • 保护程序安全,防止核心API被随意篡改

避免类的重复加载

采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子类加载器再加载一次。

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

保护程序安全,防止核心API被随意篡改,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心 Java API 发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心 API 库被随意篡改。

举个例子 双亲委派模型如何保护程序安全,防止核心API被随意篡改

举个例子,假设在Java程序中,我们需要使用一个名为 java.lang.Object 的类。当我们创建一个新的对象时,Java虚拟机会首先查找当前线程的类加载器是否已经加载了 java.lang.Object 类。如果没有加载,Java虚拟机会将该请求委托给父类加载器。如果父类加载器也没有加载该类,Java虚拟机会继续向上委托,直到委托到启动类加载器(Bootstrap ClassLoader)为止。只有当启动类加载器也无法加载该类时,Java虚拟机才会使用当前线程的类加载器加载该类。

双亲委派模型保证了类的安全性,因为在委托加载类的过程中,Java虚拟机会首先尝试使用启动类加载器加载类。启动类加载器只加载Java核心类库中的类,这些类都是由Java官方提供并经过严格测试的,不存在安全漏洞。如果使用自定义的类加载器加载类,由于自定义的类加载器可能会加载用户自定义的类或第三方类库,这些类可能存在安全漏洞或恶意代码。因此,通过双亲委派模型,Java程序可以保证只加载来自可信源的类,从而提高了Java程序的安全性。

自定义类加载器

除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader。如果我们要自定义自己的类加载器,同样需要继承 ClassLoader。

如何打破双亲委派模型

自定义加载器的话,需要继承 ClassLoader 。如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 ClassLoader 类中的 loadClass() 方法。

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

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

相关文章

腾讯云镜YunJing——Agent定时任务脚本分析

缘起 如果你有台腾讯云主机&#xff0c;会发现默认有个叫 YunJing 的进程。 把它kill掉后&#xff0c;发现一段时间又出现了 这是为什么捏&#xff1f; 分析定时任务配置文件 通过crontab定时任务目录, 会发现有个叫yunjing的配置文件。 */30 * * * * root /usr/local/qc…

PCIe物理层详细总结-PCIE专题知识(一)

目录 一、简介二、PCIe物理层结构及功能2.1 PCIe端对端连接方式2.2 PCIe组成2.2.1 逻辑层(Logic)1 发送逻辑2 接收逻辑 2.2.2 电气层(Electrical)1 物理层-电气(Physical Layer Electrical)2 数据传送----差分方式 2.2.3 PLP介绍 三、其他相关链接1、PCI总线及发展历程总结 一、…

ChatGPT 和 Elasticsearch:OpenAI 遇见私有数据(一)

作者&#xff1a;Jeff Vestal 结合 Elasticsearch 的搜索相关性和 OpenAI 的 ChatGPT 的问答功能来查询你的数据。 在此博客中&#xff0c;你将了解如何使用 Elasticsearch 将 ChatGPT 连接到专有数据存储&#xff0c;并为你的数据构建问答功能。 ChatGPT 和 Elasticsearch&…

【react从入门到精通】React JSX详解

文章目录 前言React技能树什么是JSXJSX的基本语法规则1.JSX必须有一个顶层元素2.JSX标签必须有一个结束标记&#xff0c;或者是自闭合的3.JSX中可以使用JavaScript表达式4.JSX中的样式和HTML中的样式有所不同5.JSX中的class属性必须写成className6.JSX中的style属性必须使用对象…

JavaWeb-HTML常用标签了解(一)

这里写目录标题 注释标签标题标签段落标签换行标签格式化标签图片标签超链接标签外部链接与内部链接 注释标签 <!-- 有注释 -->无注释ctrl / 快捷键可以快速进行注释/取消注释. 注意 注释不能传达负能量!!! 标题标签 有六个, 从 h1 - h6. 数字越大, 则字体越小. <h…

读SQL进阶教程笔记14_SQL编程要点

1. 消灭NULL 1.1. NULL惹人讨厌的原因 1.1.1. 进行SQL编码时&#xff0c;必须考虑违反人类直觉的三值逻辑 1.1.2. 指定IS NULL、IS NOT NULL的时候&#xff0c;不会用到索引&#xff0c;SQL语句执行起来性能低下 1.1.2.1. 1 NULL NULL2- NULL NULL3 &#xff0a; NULL …

BrainStat:用于全脑统计和多模态特征关联的工具箱

BrainStat工具箱在茗创科技往期推文【点此阅读→资源分享 | 利用机器学习进行高级MRI分析】中作过简单介绍。近日&#xff0c;NeuroImage杂志发布了题为BrainStat: a toolbox for brain-wide statistics and multimodal feature associations的预印版文章。这篇文章详细阐述了B…

测试开发备战秋招面试5-牛客刷题之链表篇

趁着5.1假期把牛客网的必刷的TOP101过一遍&#xff0c;额&#xff0c;题目量有点大&#xff0c;争取5天给刷完吧&#xff0c;哈哈&#xff0c;加油啦。再用雷布斯的那句话来激励自己吧&#xff1a;努力了那么多年,回头一望,几乎全是漫长的挫折和煎熬。对于大多数人的一生来说,顺…

学习Python需要注意什么?分享一下如何提升写代码的质量

作为程序员&#xff0c;每天都会面对各种各样的问题和挑战。需求的变更、代码的维护和修复、测试的问题&#xff0c;以及线上出现的各种异常等等&#xff0c;这些都需要我们不断地投入精力去解决。但是&#xff0c;我们不能只关注在解决问题上&#xff0c;还需要关注代码质量。…

IDE - Android Studio/Xcode历史版本下载

文章目录 前言Android Studio1. 历史版本下载2. 文件完整性校验 Xcode1. 历史版本下载2. 网络环境模拟工具2.1 下载2.2 安装2.3 卸载 最后 前言 最近升级开发工具老是遇到各种兼容性问题导致需要降回老版本&#xff0c;Xcode历史版本下载方便倒还好&#xff0c;Android Studio…

使用pands.rolling方法实现移动窗口的聚合计算

一个问题举例 假设有一个5天的收益数据&#xff0c;需要每3天求出一次平均值来达成某个需求&#xff1a; daterevenue2023-05-01102023-05-02202023-05-03302023-05-04402023-05-0550 1号、2号和3号的数据求一次平均值&#xff0c;2号、3号和4号的数据求一次平均值&#xff…

Ucore lab4

实验目的 了解内核线程创建/执行的管理过程了解内核线程的切换和基本调度过程 实验内容 练习一&#xff1a;分配并初始化一个进程控制块 1.内核线程及管理 内核线程是一种特殊的进程&#xff0c;内核线程与用户进程的区别有两个&#xff1a;内核线程只运行在内核态&#x…

内网渗透(六十一)之Kerberosating攻击

Kerberosating攻击 Kerberosating攻击发生在Kerberos协议的TGS_REP阶段,KDC的TGS服务返回一个由服务Hash 加密的ST给客户端。由于该ST是用服务Hash进行加密的,因此客户端在拿到该ST后可以用于本地离线爆破。如果攻击者的密码字典足够强大,则很有可能爆破出SPN链接用户的明文…

JAVA入坑之GUI编程

一、相关概述 GUI编程是指通过图形化的方式来实现计算机程序的编写&#xff0c;它可以让用户通过鼠标、键盘等设备来操作计算机&#xff0c;而不是通过命令行来输入指令。在Java中&#xff0c;GUI编程主要使用的是Swing和AWT两种技术 二、AWT 2.1介绍 AWT是Java提供的用来建立…

【构造】CF851div2 C. Matching Numbers

Problem - C - Codeforces 题意&#xff1a; 有1~2*n的一个排列&#xff0c;进行数与数之间两两匹配&#xff0c;问如何组合可以使n个 数对 aibi排列起来是一个连续序列&#xff0c;如果无解输出No 思路&#xff1a; 构造题&#xff0c;考虑将构造的条件特殊化 手推样例可知…

【数据生成】——Semantic Image Synthesis via Diffusion Models语义分割数据集生成论文浅读

语义分割&#xff0c;数据生成 摘要 Denoising Diffusion Probabilistic Models (DDPMs) 在各种图像生成任务中取得了显著的成功&#xff0c;相比之下&#xff0c;生成对抗网络 (GANs) 的表现不尽如人意。最近的语义图像合成工作主要遵循事实上的基于 GAN 的方法&#xff0c;…

QT QHBoxLayout 水平布局控件

本文详细的介绍了QHBoxLayout控件的各种操作&#xff0c;例如&#xff1a;新建界面、添加控件、布局控件、显示控件、添加空白行、设置间距 、添加间距、设置位置、设置外边距、设置边距、添加固定宽度、方向上、方向下、方向左、方向右等等、 样式表等操作。 实际开发中&#…

无距离障碍:远程桌面Ubuntu实现全球办公【内网穿透】

目录 前言 视频教程 1. ubuntu安装XRDP 2.局域网测试连接 3. Ubuntu安装cpolar内网穿透 4.cpolar公网地址测试访问 5.固定域名公网地址 [TOC] 转载自远程穿透文章&#xff1a;Windows通过RDP异地远程桌面Ubuntu【内网穿透】 前言 XRDP是一种开源工具&#xff0c;它允许…

范数详解-torch.linalg.norm计算实例

文章目录 二范数F范数核范数无穷范数L1范数L2范数 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 范数是一种数学概念&#xff0c;可以将向量或矩阵映射到非负实数上&#xff0c;通常被…

Python使用pytorch深度学习框架构造Transformer神经网络模型预测红酒分类例子

1、红酒数据介绍 经典的红酒分类数据集是指UCI机器学习库中的Wine数据集。该数据集包含178个样本&#xff0c;每个样本有13个特征&#xff0c;可以用于分类任务。 具体每个字段的含义如下&#xff1a; alcohol&#xff1a;酒精含量百分比 malic_acid&#xff1a;苹果酸含量&a…