【JAVA基础】JVM之类加载--双亲委派机制

news2024/12/23 4:54:03

目录

      • 1. 类加载的过程
        • 描述:
        • 看图:
        • 解释:
      • 2. 那么类加载器都有哪些呢
      • 3. 双亲委派机制
        • 3.1 双亲委派机制的过程
        • 3.2 图看委派过程
        • 3.3 为什么要设计双亲委派机制
      • 4. 自定义类加载器
        • 4.1 如何定义自己的类加载器?

1. 类加载的过程

描述:

我们写的.java文件通过编译成字节码文件.class文件,然后再通过我们的类加载器:Class Loader,反射以后,类模板存在方法区,把实例化的对象存在堆里;

看图:

在这里插入图片描述
对象的hashcode值

在这里插入图片描述

解释:
  • 从图中我们可以看出,从同一个类模板new出来三个对象(实例化过程)car1、car2、car3,而他们通过car1.hashCode(); car2.hashCode(); car3.hashCode()得到的hashCode码是不一样的(说明通过new关键字得到的对象不一样);
  • 但是通过 car1.getClass();car2.getClass();car3.getClass();得到的类模板是一样的。(说明是从同一个类模板new出来对象)

总结:

  • 对象. getClass()->获得 类模板;
  • 类模板. getClassLoader()->获得 类加载器

2. 那么类加载器都有哪些呢

类加载器主要分为四种:

  • 1.虚拟机自带的加载器
  • 2.根加载器(启动类加载器)(BootstrapClassloader)
  • 3.扩展类加载器(ExtClassloader) (JKD1.8之后为PlatformClassLoader平台类加载器 )
  • 4.应用程序类加载器(AppClassLoader)一般来说,Java 应用的类都是由它来完成加载的

扩展类加载器(Extension ClassLoader)和 应用程序类加载器(Application ClassLoader)是继承自抽象类java.lang.ClassLoader。

需要注意的是:各个类加载器之间是组合关系,并非继承关系

3. 双亲委派机制

那么到底该有哪个类去加载呢 ?所以我们在这引出双亲委派机制;

3.1 双亲委派机制的过程

一句话:向上委派,上面能加载就会加载;

  • 类加载器受到加载类的请求
  • 然后将这个请求向上委托给父类加载器去完成,一直向上委托:
    App -> Platform -> Bootstrap 直至到根加载器-Bootstrap
  • 根加载器Bootstrap会检查是否能加载当前这个类,(比如java.lang包下的所有类,根加载器都能加载);
    • 若能加载就由根加载器来加载这个类,加载到此结束;
    • 若不能加载,则才向下传递 Bootstrap -> Platform -> App直至有加载器来加载,不然就会报错;比如ClassNotFound

一般来说,Java 应用的类都是由AppClassLoader来完成加载的

总结

如果一个类加载器收到了类加载的请求,它首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是加此,因此所有的加载请求最终到达顶层的启动类加载器,只有当父类加载器反馈自己无法完成加载请求时,子类加载器才会尝试自己去加载。

3.2 图看委派过程

在这里插入图片描述

从上图中我们就更容易理解了:

当一个.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。

如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。

注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException

那么有人就有下面这种疑问了?
为什么要有这种机制?

3.3 为什么要设计双亲委派机制

这种设计的好处:

  • 可以确保安全性。
    如果有人想替换系统级别的类:如String.java,篡改它的实现。双亲委派机制可以保证所有的Java类库都是由启动类加载器加载Bootstrap classLoader,从一定程度上防止了危险代码的植入;
  • 可以避免重复加载
    当父亲已经加载了该类的时候,就没有必要让子加载器再加载一次;

面试常问
问: 比如我们自己重新定义一个完全和String同包名的类: java.lang.String类,那么此时jdk加载的是系统自己的String还是我们的String?

答案:当然是系统自己的String类, 也就是说:我们自己写的java.lang.String的类,是不可以替换调JDK本身的类。
为什么呢?虽然和双亲委派机制有关系,但不是非常的准确。因为双亲委托派机制是可以打破的,我们完全可以自己写一个classLoader来加载自己写的java.lang.String类,但是我们会发现也不会加载成功;
真正的原因:
因为针对java.*开头的类,jvm的实现中已经保证了必须由Bootstrap classLoader ,也就是我们的根加载器来加载。

具体描述:
在加载某个类时,优先使用父类加载器加载。如果我们自定义了java.lang.String这个类, 那么该自定义String类使用的加载器应是是AppClassLoader,根据双亲委派原理, AppClassLoader加载器的父类为ExtClassLoader,所以这时加载String使用的类加载器是ExtClassLoader, 但是类加载器ExtClassLoader在jre/lib/ext目录下没有找到String.class类。 然后使用ExtClassLoader父类的加载器BootStrap, 父类加载器BootStrap在jre/lib目录的rt.jar找到了String.class,将其加载到内存中。而jre/lib目录下的 String类 就是我们jdk自己的类。

4. 自定义类加载器

问: 既然JVM已经提供了默认的类加载器,为什么还要自已来定义类加载器呢?

答: 因为Java中提供的默认ClassLoader,只加载指定目录下的jar和class,如果我们想加载其它位置的类或jar时,比如:我们想要加载网络上的一个.class文件,加载到内存之后,我们想要调用这个类中的方法实现自己的业务逻辑。在这样的情况下,默认的ClassLoader就不能满足我们的需求了,所以需要定义自己的ClassLoader。

4.1 如何定义自己的类加载器?

定义自已的类加载器分为两步:

  • 继承java.lang.ClassLoader

  • 重写父类的findClass方法

问: 为什么只重写findClass方法?

答: 因为JDK已经在loadClass方法中帮我们实现了ClassLoader搜索类的算法,当在loadClass方法中搜索不到类时,loadClass方法就会调用findClass方法来搜索类,所以我们只需重写该方法即可。

但是,如没有特殊的要求,一般不建议重写loadClass搜索类的算法。

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

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

相关文章

kylin集群反向代理(健康检查)

前面一篇文章提到了使用nginx来对kylin集群进行反向代理, kylin集群使用nginx反向代理-CSDN博客文章浏览阅读349次,点赞8次,收藏9次。由于是同一个集群的,元数据没有变化,所以,直接将原本的kylin使用scp的…

21道Java Spring MVC综合面试题详解含答案(值得珍藏)

1.概述 1.1 什么是Spring MVC?简单介绍下你对Spring MVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷⑩

单元测试 一、任务要求 题目1:根据下列流程图编写程序实现相应处理,程序根据两个输入参数iRecordNum和IType计算x的值并返回。编写程序代码,使用JUnit框架编写测试类对编写的程序代码进行测试,测试类中设计最少的测试数据满足基路…

Windows安装Rust环境(详细教程)

一、 安装mingw64(C语言环境) Rust默认使用的C语言依赖Visual Studio,但该工具占用空间大安装也较为麻烦,可以选用轻便的mingw64包。 1.1 安装地址 (1) 下载地址1-GitHub:Releases niXman/mingw-builds-binaries GitHub (2) 下载地址2-W…

C#编程-实现线程声明周期

实现线程声明周期 当System.Threading.Thread类的对象被创建的时候,线程的生命周期开始。线程的生命周期在完成任务时结束。在线程的生命周期中有各种状态。这些状态是: 未启动状态可运行状态不可运行状态死亡状态下图显示了线程的各种状态和引起线程从一个状态变为另一个状…

上市路上,如何打好合规与增长的双赢之战? |CFO x CIO 专刊

经济发展的新旧动能转化之下,企业需要找到可持续的高质量发展之路。以数字化智能化为推动力,做好内控与合规,不仅能保证企业的发展不偏离航道,还能有效激发数字资产价值,帮企业获得新发展动能。不管是拟上市企业还是已…

STM32F107VCT6官方原理图和PCB

资料下载地址:STM32F107VCT6官方原理图和PCB STM32F107VCT6是STMicroelectronics公司推出的一款高性能的32位微控制器芯片。它采用了ARM Cortex-M3架构,工作电压范围为2.0V-3.6V,主频速度高达72MHz,能够运行多重模式的程序。 在存…

二叉树题目:完全二叉树插入器

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题:完全二叉树插入器 出处:919. 完全二叉树插入器 难度 6 级 题目描述 要求 完全二叉树是每一层(除最后一层外)都…

线索系统性能优化实践

引言 在京东家居事业部,线索CRM系统扮演着至关重要的角色,它作为构建家居场景核心解决方案集的首要环节,肩负着获客和拓展业务的重要使命。然而,随着业务的不断扩张和市场需求的日益增长,系统原有的架构开始显露出诸多…

DDMS修改默认端口8700

当前操作系统为 Mac,编辑器 Intellij IDE 准备工作:在IDE中的终端下,输入monitor指令 > 回车,打开DDMS 1、第一步, 2、第二步:修改静态端口 3、第三步 4、第四步:修复配置端口 5、第五步 重…

高级路由学习试题

文章目录 高级路由学习试题一.高级路由题目答案 二.OSPF 相关答案 三.基础知识答案 高级路由学习试题 一.高级路由题目 1.以下属于ITOIP特性的有() A、智能 B、开放 C、融合 D、标准 2.层级化网络模型将网络划分为() A、汇…

[Kubernetes]9. K8s ingress讲解借助ingress配置http,https访问k8s集群应用

前面讲解了使用Helm部署mysql集群,这里来看看使用Ingress搭建负载均衡功能 1.介绍 功能类似 Nginx ,可以根据域名、路径把请求转发到不同的 Service , Ingress 为外部访问集群提供了一个 统一 入口, 避免 了 对外暴露集群端口 ,可以配置 https,http访问集群应用,接下来看看如…

实现STM32烧写程序-(1)获取Bootloader版本信息

简介 如何像ST Flash Loader等工具一样写自己的烧写程序呢?文档 AN3155: USART protocol used in the STM32 bootloader 步骤 Boot模式 将 开发板例如STM32F103C8T6 Boot0->1 & Boo1->0 重启或复位进入系统存储模式 物理连接 将USART1 通过 USB转TTL线连接到…

大模型学习与实践笔记(五)

一、环境配置 1. huggingface 镜像下载 sentence-transformers 开源词向量模型 import os# 设置环境变量 os.environ[HF_ENDPOINT] https://hf-mirror.com# 下载模型 os.system(huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-…

一卡通水控电控开发踩过的坑

最近在做一个项目,是对接一卡通设备的。我一开始只拿到设备和3个文档开局。不知道从哪下手。一步一步踩坑过来。踩了很多没有必要的坑,写出来给有用的人吧。 读卡器怎么用? 有个读卡器,一开始什么软件也不提供。我都不知道是干嘛…

Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c…

NLP论文阅读记录 - 05 | 2023 抽象总结与提取总结:实验回顾

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1 提取方法2.2 抽象方法2.3 数据集 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Abstractive vs. Extractiv…

从头安装与使用一个docker GPU环境

GPU版docker的安装与使用 欢迎使用GPU版docker安装使用说明使用官方教程安装docker新建一个GPU版docker环境调用docker环境执行本地python文件 欢迎使用GPU版docker安装使用说明 使用官方教程安装docker 导入源仓库的GPG key curl -fsSL https://download.docker.com/linux/…

RTL编码(1)——概述

一、RTL级描述 RTL(Register Transfer Level)级:寄存器+组合逻辑,其功能与时序用Verilog HDL(以下简称Verilog)或VHDL代码描述。 RTL描述包含了同步数字电路最重要的三个特征:组合逻…

水产冷链物流行业零下25℃库架一体 海格里斯HEGERLS四向穿梭式冷藏冷库智能密集仓

随着国内外仓储物流整体规模和低温产品消费需求的稳步增长,冷链市场应用潜力不断释放。在传统“货架叉车”的方式下,货物、人员及机械设备不断进出,容易造成温度波动,导致冷量流失。立体冷库则以更高密度、更具成本效益的方式&…