类加载机制及双亲委派模型

news2025/2/23 4:49:38

一、引言

二、类加载流程

 1. 加载

2. 连接 

        2.1 验证

         2.2 准备

        2.3 解析

3. 初始化

三、类加载器

    类加载器的类型

     双亲委派模型

打破双亲委派模型

双亲委派模型优点

一、引言

在 Java 的运行机制中,类加载是一个至关重要的环节。它不仅决定了 Java 程序的动态性和灵活性,还为 Java 的安全性和稳定性提供了基础保障。类加载机制的核心在于类加载器(ClassLoader),它负责将字节码文件加载到 Java 虚拟机(JVM)中,并将其转换为可执行的类对象。这一过程不仅涉及到类的加载、解析和初始化,还通过双亲委派模型确保了类加载的安全性和一致性。

本文将深入探讨 Java 类加载的完整流程。同时,我将介绍双亲委派模型的原理及其优势,以及如何通过自定义类加载器打破这一模型以满足特定需求。希望读者能掌握如何在实际开发中利用这一机制实现灵活的类加载策略。

二、类加载流程

首先我们要知道类加载的流程,

类加载的过程主要分三步:加载 ——连接——初始化

而连接这一步又分了三步:验证——准备——解析

这里我们绘制了一个图片描述了类加载的流程。

 1. 加载

 这是类加载器的第一步

首先我们通过全限定名获取到当前类的二进制流;

然后我们把字节流代表的静态存储结构转换为方法区的运行时数据结构(类的结构信息,常量池,字段信息,静态变量等等)Classloader通过defineClass将字节流数据转化class对象。defineClass只是个入口,该过程是在JVM底层实现。

    protected final Class<?> defineClass(String name, byte[] b, int off, int len)
        throws ClassFormatError
    {
        return defineClass(name, b, off, len, null);
    }

2. 连接 

        2.1 验证

  • 主要是为了确保字节流信息符合.class规范,Java的.class文件开头魔数是0xCAFEBABE,通过他就可以校验是否是Java文件了,满足了魔数还要判断以下内容

  • 元数据:检查元数据是否符合语义,是否有重复字段?不允许继承的类?等等……
  • 字节码验证:检查字节码是否符合规范,类型转化是否正确
  • 符号引用验证:是否引用了不能别的类而权限不正确       

         2.2 准备

        主要是为静态变量分配内存,并设置初始值,如果使用了final修饰还会直接为他附上初值

        2.3 解析

        把符号引用转换成直接引用的过程

3. 初始化

             初始化是类加载的最后一步,执行了类的初始化代码<clinit>()(编译后自动生成)

    包括静态变量的赋值,静态代码块,很经典的一道题就是父子类的代码块顺序问题,答案如下

    1. 父类的静态变量赋值。

    2. 父类的静态代码块执行。

    3. 当前类的静态变量赋值。

    4. 当前类的静态代码块执行。

    类加载触发初始化的条件:

            初始化阶段的执行是类加载机制的一部分,但并不是所有类加载都会触发初始化。根据 Java 规范,以下情况会触发类的初始化:

    1. 创建类的实例

      • 通过 new 关键字创建类的实例。

      • 通过反射创建类的实例。

      • 通过克隆(clone)创建类的实例。

    2. 调用静态方法或访问静态字段

      • 调用类的静态方法。

      • 访问类的静态字段(除了通过 Class.forName 加载类但不执行初始化的情况)。

    3. 子类初始化

      • 如果子类初始化,则父类也会被初始化。

    4. JVM启动时加载的类

      • JVM 启动时加载的主类(如 public static void main(String[] args) 所在的类)。

     

    三、类加载器

            类加载器的主要功能就是加载字节码到JVM中去,他赋予了Java类动态加载到JVM并执行的能力。类加载器是一个负责加载类的对象。ClassLoader 是一个抽象类。给定类的二进制名称,类加载器应尝试定位或生成构成类定义的数据。典型的策略是将名称转换为文件名,然后从文件系统中读取该名称的“类文件”。每个 Java 类都有一个引用指向加载它的 ClassLoader

        类加载器的类型

    • BootstrapClassLoader:启动类加载器,最顶级加载器,没有父类,获取父类得到他的时候会返回null,是由c++实现的。
    • ExtensionClassloader:扩展类加载器,加载jar包以及系统变量指定路径下的类
    • AppClassLoader:应用程序类加载器,面向用户加载器,加载classpath下的所有jar包和类

            我们还可以加入自定义类加载器,暂且不提。

         双亲委派模型

            既然我们有了这么多类加载器,那么我们使用的时候会如何选择呢?

            这就提到了我们的双亲委派模型:每次查找的时候,每一级ClassLoader 都会把搜索类或者资源的任务委托给父类加载器(也是防止重复加载),如果父类加载器找不到再给到下一级

    执行流程:这里我们贴上源码

    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
                        PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }

    可以看到我们首先通过本地方法findLoadedClass查找是否被加载过

    如果没有被加载过再进入下一步,如果父类加载器不为空,就调用父类加载器的loadClass

    如果没有父类加载器(parent == null),则尝试通过根加载器加载类(通过 findBootstrapClassOrNull(name) 方法)。

    如果父类加载器(或引导类加载器)无法加载类,则调用当前类加载器的 findClass(String name) 方法来加载类。

    基本流程也就结束了

    打破双亲委派模型

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

    双亲委派模型优点

    避免了类的重复加载,父加载器加载过了子类不会加载。

    保证了Java核心的API不被篡改,不然我自己写一个Object类JVM直接使用了,但是我有双亲委派,他会一直找到根加载器找到核心API


    写到这里我们就了解了JVM的类加载机制已经双亲委派模型,希望各位大佬多多指教!

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

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

    相关文章

    尚硅谷课程【笔记】——大数据之Hadoop【一】

    课程视频链接&#xff1a;尚硅谷Hadoop3.x教程 一、大数据概论 1&#xff09;大数据概念 大数据&#xff08;Big Data&#xff09;&#xff1a;指无法再一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发…

    DockerFile优化镜像体积

    title: DockerFile优化镜像体积 date: 2025-02-15 15:22:40 tags: DockerFile优化镜像体积DockerFile优化镜像体积 DockerFile优化镜像体积前文回顾:一、细数优化镜像体积的思路与方式二、优化Dockfile文件编辑 Dockerfile2文件三、构建镜像四、运行镜像五、查看运行效果原文 …

    题解:洛谷 P4113 [HEOI2012] 采花

    题目https://www.luogu.com.cn/problem/P4113 运用类似于P1972 [SDOI2009] HH的项链的操作&#xff0c;将数据离线下来处理。 按照区间右端点从小到大排序。 问题是数量大于等于 的时候才能算进去。 于是乎我们用两个数组维护倒数第二次出现和最后一次出现的地方。 每次在…

    easyexcel快速使用

    1.easyexcel EasyExcel是一个基于ava的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel 即通过java完成对excel的读写操作&#xff0c; 上传下载 2.easyexcel写操作 把java类中的对象写入到excel表格中 步骤 1.引入依赖 <depen…

    android studio下载安装汉化-Flutter安装

    1、下载android studio官方地址&#xff1a;&#xff08;这个网址可能直接打不开&#xff0c;需要VPN&#xff09; https://developer.android.com/studio?hlzh-cn mac版本分为X86和arm版本&#xff0c;电脑显示芯片是Inter的就是x86的&#xff0c;显示m1和m2的就是arm的 …

    Seaweedfs(master volume filer) docker run参数帮助文档

    文章目录 进入容器后执行获取weed -h英文中文 weed server -h英文中文 weed volume -h英文中文 关键点测试了一下&#xff0c;这个-volume.minFreeSpace string有点狠&#xff0c;比如设置值为10&#xff08;10%&#xff09;&#xff0c;它直接给系统只留下10%的空间&#xff0…

    【工业安全】-CVE-2022-35555- Tenda W6路由器 命令注入漏洞

    文章目录 1.漏洞描述 2.环境搭建 3.漏洞复现 4.漏洞分析 4.1&#xff1a;代码分析  4.2&#xff1a;流量分析 5.poc代码&#xff1a; 1.漏洞描述 漏洞编号&#xff1a;CVE-2022-35555 漏洞名称&#xff1a;Tenda W6 命令注入 威胁等级&#xff1a;高危 漏洞详情&#xff1…

    C#(Winform)通过添加AForge添加并使用系统摄像机

    先展示效果 AForge介绍 AForge是一个专门为开发者和研究者基于C#框架设计的, 也是NET平台下的开源计算机视觉和人工智能库 它提供了许多常用的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;并且具有高效、易用、稳定等特点。 AForge主要包括: 计算机视觉与人…

    【LeetCode: 611. 有效三角形的个数 + 排序 + 双指针】

    &#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

    每日十题八股-补充材料-2025年2月15日

    1.TCP是如何保证消息的顺序和可靠的&#xff1f; 写得超级好的文章 首先肯定是三次握手和四次挥手保证里通讯双方建立了正确有效的连接。 其次是校验和、序列号&#xff0c;ACK消息应答机制还有重传机制&#xff0c;保证了消息顺序和可靠。 同时配合拥塞机制和流量控制机制&am…

    国内已经部署DeepSeek的第三方推荐

    大家好&#xff0c;我是苍何。 最近DeepSeek爆火&#xff0c;我也说点心里话&#xff0c;其实就我们普通人而言&#xff0c;要想用好 DeepSeek&#xff0c;其实无非就是要利用好工具为我们自己提效。 比如你是搞编程的&#xff0c;你就得学会如何用 DeepSeek 更快速的辅助你编…

    Windows环境下使用Ollama搭建本地AI大模型教程

    注&#xff1a;Ollama仅支持Windows10及以上版本。 安装Ollama 去 ollama官网 下载对应平台及OS的安装包。 运行安装包&#xff0c;点击“安装”按钮即可开始安装。Ollama会自动安装到你的 C:\Users\<当前用户名>\AppData\Local\Programs\Ollama 目录上。 安装完成后&…

    2024年认证杯SPSSPRO杯数学建模A题(第二阶段)保暖纤维的保暖能力全过程文档及程序

    2024年认证杯SPSSPRO杯数学建模 A题 保暖纤维的保暖能力 原题再现&#xff1a; 冬装最重要的作用是保暖&#xff0c;也就是阻挡温暖的人体与寒冷环境之间的热量传递。人们在不同款式的棉衣中会填充保暖材料&#xff0c;从古已有之的棉花、羽绒到近年来各种各样的人造纤维。不…

    算法19(力扣244)反转字符串

    1、问题 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 2、示例 &#xff08;1&#xff09; 示例 1&a…

    DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)

    前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

    ESP32 arduino + DeepSeek API访问

    此项目主要使用ESP32-S3实现一个AI语音聊天助手&#xff0c;可以通过该项目熟悉ESP32-S3 arduino的开发&#xff0c;百度语音识别&#xff0c;语音合成API调用&#xff0c;百度文心一言大模型API的调用方法&#xff0c;音频的录制及播放&#xff0c;SD卡的读写&#xff0c;Wifi…

    最新国内 ChatGPT Plus/Pro 获取教程

    最后更新版本&#xff1a;20250202 教程介绍&#xff1a; 本文将详细介绍如何快速获取一张虚拟信用卡&#xff0c;并通过该卡来获取ChatGPT Plus和ChatGPT Pro。 # 教程全程约15分钟开通ChatGPT Plus会员帐号前准备工作 一个尚未升级的ChatGPT帐号&#xff01;一张虚拟信用卡…

    SQLMesh 系列教程4- 详解模型特点及模型类型

    SQLMesh 作为一款强大的数据建模工具&#xff0c;以其灵活的模型设计和高效的增量处理能力脱颖而出。本文将详细介绍 SQLMesh 模型的特点和类型&#xff0c;帮助读者快速了解其强大功能。我们将深入探讨不同模型类型&#xff08;如增量模型、全量模型、SCD Type 2 等&#xff0…

    渗透利器:YAKIT 工具-基础实战教程.

    YAKIT 工具-基础实战教程. YAKIT&#xff08;Yak Integrated Toolkit&#xff09;是一款基于Yak语言开发的集成化网络安全单兵工具&#xff0c;旨在覆盖渗透测试全流程&#xff0c;提供从信息收集、漏洞扫描到攻击实施的自动化支持。其核心目标是通过GUI界面降低Yak语言的使用…

    jenkins 配置ssh拉取gitlab

    一、生成key ssh-keygen -t rsa -b 4096 -C "root" 二、将id_rsa内容拷贝到jenkins 公钥id_rsa.pub拷贝到gitlab