类与类加载器

在Java中,类和类加载器是密切相关的两个概念,理解它们有助于我们更好地掌握Java的运行机制。

什么是Java类?

Java类就像是一个模板或蓝图,它定义了对象的属性和行为。比如"汽车"可以看作一个类,它有颜色、品牌等属性,有行驶、刹车等行为。我们根据这个类可以创建具体的汽车对象(如一辆红色的特斯拉)。

// 汽车类(模板)
class Car {String color;  // 属性String brand;  // 属性// 行为void drive() {System.out.println(brand + "汽车正在行驶");}
}// 创建对象(根据模板造具体的车)
Car myCar = new Car();
myCar.color = "红色";
myCar.brand = "特斯拉";
myCar.drive();  // 输出:特斯拉汽车正在行驶

什么是类加载器?

类加载器(ClassLoader)就像是"类的搬运工",它的作用是把.class文件(编译后的类)加载到Java虚拟机(JVM)中,让JVM能够认识这个类并使用它。

想象一下:JVM就像一个大型工厂,类就像是生产所需的图纸。类加载器的工作就是把这些图纸从文件系统、网络或其他地方运送到工厂里,供工厂使用。

咱们可以把Java虚拟机(JVM)想象成一个“大工厂”,类加载器就是负责给这个工厂“运图纸(类)”的工人。

从虚拟机角度看(两种类加载器)

  • 启动类加载器(Bootstrap ClassLoader):它是工厂里“最核心的元老级搬运工”,用C++写的,是虚拟机本身的一部分。专门搬最基础、最核心的“工厂自带图纸”,像java.lang.String这类Java最根本的类,就靠它搬。
  • 其他类加载器:这些是“后来的搬运工”,用Java写的,和虚拟机是分开的。它们都得继承java.lang.ClassLoader这个抽象类,负责搬一些额外的图纸。

从开发者角度看(更细致的划分)

  • 启动类加载器:还是那个“核心元老搬运工”,负责搬<JRE_HOME>\lib目录里(或者-Xbootclasspath参数指定路径里)、虚拟机能认出来的“核心图纸”。比如java.util(工具类)、java.io(输入输出类)、java.lang(语言基础类)这些常用基础类库。而且它很“傲娇”,只认文件名,像rt.jar这类符合名字的才搬,名字不对的,哪怕在lib目录里也不管。另外,Java程序没法直接调用它。

  • 扩展类加载器(Extension ClassLoader):它是“扩展搬运工”,负责搬<JRE_HOME>/lib/ext目录或者java.ext.dir系统变量指定路径里的“扩展图纸”。像swing(界面相关)、内置js引擎、xml解析器这些以javax开头的扩展类库,都由它来搬。开发者是可以直接用这个加载器的。

  • 应用程序类加载器(Application ClassLoader):也叫“系统类加载器”,是“用户搬运工”。负责搬用户自己指定的类路径(ClassPath)里的“图纸”,比如我们自己写的类,或者第三方的jar包。如果我们没自己定义类加载器,程序默认就用它来搬图纸。而且它可以通过ClassLoadergetSystemClassLoader()方法获取到,开发者能直接使用。

类与类加载器的关系

  • 每个类被加载到JVM后,都会记录是被哪个类加载器加载的
  • 类加载器之间存在"父子关系":Application的父是Extension,Extension的父是Bootstrap
  • 判断两个类是否相同,不仅要看类名是否一样,还要看它们是否被同一个类加载器加载

打个比方:两个名字相同的"汽车"图纸,如果一个是由"中国搬运工"搬来的,一个是由"美国搬运工"搬来的,JVM会认为它们是不同的类。

为什么需要类加载器?

  1. 实现了类的动态加载:需要用某个类时才加载,不用时不加载,节省资源
  2. 实现了隔离性:不同的类加载器可以加载同名类而不冲突,这对容器(如Tomcat)很重要
  3. 安全性:可以通过自定义类加载器来控制哪些类能被加载,防止恶意代码

理解类和类加载器的关系,有助于我们解决类冲突、类找不到等问题,也是学习Java反射、动态代理等高级特性的基础。

在Java类加载机制中,双亲委派模型可以类比成一个公司的文件审批流程,这样能更通俗易懂地理解。

什么是双亲委派模型

在Java里,类加载器之间存在层次关系,形成了一个类似树形的结构。除了最顶层的启动类加载器 ,其他类加载器都有自己的“父加载器”,比如扩展类加载器的父加载器是启动类加载器,应用程序类加载器的父加载器是扩展类加载器。双亲委派模型规定,当一个类加载器收到类加载请求时,它首先不会自己去尝试加载这个类,而是把请求委派给父加载器去完成,只有当父加载器无法完成加载任务时,子加载器才会尝试自己去加载。

用公司审批流程举例说明

假设你在公司里写了一份重要的报告,需要经过审批才能正式发布。这就类似于类加载器收到加载类的请求。

  • 部门经理(应用程序类加载器):你作为普通员工,写好报告后会先交给部门经理,对应应用程序类加载器收到类加载请求,它不会自己先去处理,而是把请求向上提交。
  • 部门总监(扩展类加载器):部门经理拿到你的报告后,不会直接审批,而是交给部门总监,这就好比应用程序类加载器把加载请求交给扩展类加载器。部门总监拿到报告后,同样也不会直接审批,而是继续往上提交。
  • 公司老板(启动类加载器):部门总监把报告交给公司老板,启动类加载器作为最顶层,先检查这个报告(类)是不是属于它负责的核心内容,比如公司的基本规章制度、财务审批流程等相关文件(Java核心类库) 。如果是,老板就直接审批(加载类);如果不是,比如是关于某个项目的具体报告,老板就会把报告打回给部门总监,说“这事儿不归我管,你处理一下”。
  • 部门总监处理:部门总监接到老板打回的报告后,查看是否属于自己职责范围内,比如一些技术规范、行业标准相关的报告,如果是就审批(加载类);如果不是,再打回给部门经理。
  • 部门经理处理:部门经理接到报告,一看是关于自己部门项目执行情况的报告,就自己审批了(应用程序类加载器自己加载类)。

双亲委派模型的好处

  • 避免重复加载:如果父加载器已经加载过这个类,子加载器就不需要再加载了,节省了资源。就像在公司审批流程中,如果高层已经审批过类似的文件,底层就不用重复审批。
  • 保证安全性:它确保了Java核心类库的一致性和安全性。因为核心类库都是由最顶层的启动类加载器加载的,防止了用户自定义的类去替换核心类。比如不会出现有人写一个假的java.lang.String类混入系统,因为启动类加载器只会加载真正的核心String类 。

对象的创建过程

咱们把Java中对象的创建过程,比作"盖房子"的过程,这样就很好理解了:

  1. 确定图纸(类加载检查)


1.当你说new 房子()时,JVM首先会检查"房子"这个类的图纸(.class文件)有没有被加载到内存里。如果没加载,就会让类加载器去把图纸搬过来(类加载过程)。
就像盖房子前,必须先有建筑图纸,而且图纸得先拿到工地才行。

  1. 圈地(分配内存)
    图纸确认后,JVM会在内存里找一块合适的地方(堆内存),专门用来盖这个房子(存放对象)。
    相当于开发商在空地上圈出一块地,大小刚好够盖这栋房子。

  1. 地基处理(初始化零值)
    圈好地后,JVM会先把这块地"打扫干净",给里面的各种属性(比如房子的面积、房间数)设置默认值(数字0、布尔false、引用null等)。
    就像盖房子前,先把地皮整平,打好地基,确保基础是合格的。

  1. 挂门牌(设置对象头)
    JVM会给这个对象加一个"身份证"(对象头),里面记录着:这个对象属于哪个类(对应哪个图纸)、哈希码、GC信息等。
    相当于给房子挂上门牌,写明"这是XX小区3号楼",方便后续查找和管理。

  1. 内部装修(执行初始化)
    最后一步是真正按照图纸装修:给属性赋值(比如面积120平米、3个房间)、执行构造方法里的逻辑(比如安装门窗、铺地板)。
    到这一步,房子才算真正盖好,能住人(使用对象)了。

总结一下:从确认图纸→分配空间→基础处理→标记身份→详细装修,一步不差,一个对象就创建出来了。就像盖房子一样,按流程来才能保证最终的"房子"能用、好用。

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

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

相关文章

一文速通Python并行计算:14 Python异步编程-协程的管理和调度

一文速通 Python 并行计算&#xff1a;14 Python 异步编程-协程的管理和调度 摘要&#xff1a; Python 异步编程基于 async/await 构建协程&#xff0c;运行在事件循环中。协程生成 Task&#xff0c;遇到 await 时挂起&#xff0c;I/O 完成触发回调恢复运行&#xff0c;通过…

Node.js面试题及详细答案120题(16-30) -- 核心模块篇

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

RabbitMQ:Windows版本安装部署

目录一、概述二、OPT三、安装RabbitMQ四、登录测试一、概述 什么是MQ&#xff0c;有什么做作用&#xff1f; MQ即MessageQueue&#xff0c;消息队列。可以分为两部分理解&#xff1a;消息Message用于在不同的应用程序中传递数据。队列Queue&#xff0c;一种FIFO先进先出的数据…

酒店行业安全体系构建与优化策略

酒店行业安全体系构建与优化策略为确保酒店行业领导及宾客的安全&#xff0c;构建全面的治安联防体系及事故处理预案至关重要。某招待所通过设立保卫部&#xff0c;细化内保、治安、防火及交通管理职能&#xff0c;并下设警卫班、监控中心和电瓶车班&#xff0c;以全方位保障安…

python30-正则表达式

在Python中需要通过正则表达式对字符串进⾏匹配的时候&#xff0c;可以使⽤⼀个python自带的模块&#xff0c;名字为re。 re模块的使用&#xff1a;import re 一、匹配函数 1-1、re.match函数&#xff1a;返回匹配对象 match函数实现的是精准匹配&#xff0c;尝试从字符串的…

EP1C12F324I7N Altera Cyclone FPGA

EP1C12F324I7N 是 阿尔特拉 Altera Cyclone 系列中的一款 SRAM-based FPGA&#xff0c;定位为低成本、低功耗、面向嵌入式与消费/工业类量产应用的器件。该器件提供约 12,060 个逻辑单元&#xff08;Logic Elements&#xff09;&#xff0c;片上嵌入式存储约 234 kbit&#xff…

html5语义元素

1、参考&#xff1a;HTML5 语义元素 | 菜鸟教程 2、实战 HTML5 <section> 元素 <section> 标签定义文档中的节&#xff08;section、区段&#xff09;。比如章节、页眉、页脚或文档中的其他部分。 根据W3C HTML5文档: section 包含了一组内容及其标题。 <!D…

java调用PyTorch 训练模型实现神经网络全流程

以下是完整的操作流程:用 PyTorch 训练模型 → 导出为 ONNX 格式 → 用 Java 加载并推理,兼顾开发效率(PyTorch 快速训练)和生产部署(Java 稳定运行)。 一、PyTorch 训练模型并导出为 ONNX 1. 安装依赖 bash pip install torch onnx # PyTorch 和 ONNX 库2. 训练一个…

Maven - Spring Boot 项目打包本地 jar 的 3 种方法

文章目录Pre概述方案思路构建流程图工作机制说明目录结构示例POM 配置模板构建与验证注意事项方案优缺点Pre Maven - Manual Maven JAR Installation&#xff1a;用 mvn install:install-file 安装本地 JAR 的实用指南 概述 在 Spring Boot 项目中&#xff0c;通常依赖包会从…

平替 Claude Code,API接入 GPT-5,Codex CLI 国内直接使用教程

最新升级接入GPT-5的 Codex 拥有可以媲美 Claude Code 的AI编码能力&#xff0c;本文将指导你在 Windows系统上部署原生的 Codex CLI程序&#xff0c;并且接入超低价中转API&#xff0c;让你在国内直接用上超高性价比的 OpenAI Codex CLI 应用。关于 CodexCodex 是 OpenAI 开发…

kubernertes (K8S)部署

参考&#xff1a; https://blog.csdn.net/yu33575/article/details/135387548 二进制安装k8s&#xff1a; https://blog.csdn.net/qq_73990369/article/details/143217084 K8S二进制安装与部署 &#xff1a;https://blog.csdn.net/fantuan_sss/article/details/139073366 k8s…

LeetCode 简单JS刷题

目录 返回数组最后一个元素 2787.将一个数字表示成幂的和的方案数 326.3的幂 1780.判断一个数字是否可以表示成三的幂的和 342.4的幂 返回数组最后一个元素 1.请你编写一段代码实现一个数组方法&#xff0c;使任何数组都可以调用 array.last() 方法&#xff0c;这个方法将…

七大排序算法全解析:从入门到精通

目录 一.排序的概念 二.常见排序算法的实现 2.1 插入排序 &#xff08;1&#xff09;直接插入排序&#xff1a; 当插入第i(i>1)个元素时&#xff0c;前面的array[0],array[1],…,array[i-1]已经排好序&#xff0c;此时用array[i]的排序码与array[i-1],array[i-2],…的排序…

20250814在荣品RD-RK3588开发板的Android13下解决卡迪的LCD屏在开机的时候brightness最暗【背光的pwm信号的极性反了】

20250814在荣品RD-RK3588开发板的Android13下解决卡迪的LCD屏在开机的时候brightness最暗【背光的pwm信号的极性反了】 2025/8/14 11:33缘起&#xff1a;在荣品RD-RK3588开发板的Android13下&#xff0c;卡迪的LCD屏在开机的时候很暗&#xff0c;几乎看不见。 在命令行查看亮度…

Flink的状态管理

一、状态的概念Flink的状态其实你就可以将其想象为中间结果就可以了。在Flink中&#xff0c;算子的任务可以分为无状态和有状态两种情况。无状态算子任务在计算过程中是不依赖于其他数据的&#xff0c;只根据当前的输入数据就可以得到结果输出。比如之前讲到的Map、FlatMap、Fi…

GoLand 项目从 0 到 1:第八天 ——GORM 命名策略陷阱与 Go 项目启动慢问题攻坚

第八天核心任务&#xff1a;解决开发中的两大技术卡点今天的开发不仅聚焦于代码层面的数据库字段映射问题&#xff0c;还遭遇了一个困扰团队许久的环境难题 ——Go 项目启动异常缓慢。经过多维度排查&#xff0c;我们不仅理清了 GORM 命名策略的设计逻辑&#xff0c;还找到了影…

在Ubuntu上安装Google Chrome的详细教程

步骤 1&#xff1a;下载 Google Chrome 安装包 打开浏览器输入https://www.google.cn/chrome/&#xff0c;然后进入Chrome浏览器官方网站 点击下载选择Debian/Ubuntu版本 google-chrome-stable_current_amd64.deb步骤 2&#xff1a;安装下载的.deb 包 sudo dpkg -i google-chro…

el-table合并相同名称的行

el-table合并相同名称的行 <template><el-table:data"tableData":span-method"objectSpanMethod"border><el-table-columnprop"name"label"名称"width"180"></el-table-column><el-table-column…

解决 VSCode 无法从右键菜单“通过 Code 打开”文件夹的问题

&#x1f9e9; 一、问题现象 VSCode 已安装&#xff0c;但右键文件夹/桌面空白处无“通过 Code 打开在 VSCode 中执行 Shell Command: Install ‘Open with Code’ 无反应手动添加后菜单显示乱码&#xff08;如 €š‡ Code ‰“€&#xff09;点击右键菜单无响应或提示“找不到…

服务器数据恢复—服务器硬盘状态灯变红,分区数据恢复过程

服务器数据恢复环境&故障&#xff1a; 某公司服务器上有一组由3块硬盘组建的raid5磁盘阵列。 服务器上1块硬盘的状态灯变为红色&#xff0c;磁盘阵列出现故障&#xff0c;分区无法识别。服务器数据恢复过程&#xff1a; 1、将故障服务器上所有磁盘编号后取出。经过初检&…