通俗易懂:什么是 Java 类加载?
文章目录
- 类加载过程的三个阶段
- 一个简单的案例:类加载的工作原理
- 使用这个类
- 类加载的顺序
- 类加载的特点
- 类加载的好处
- 总结
- 推荐阅读文章
在 Java 中, 类加载是一种将我们写的 Java 类文件加载到内存中的过程,让 JVM(Java 虚拟机)可以识别和执行它们。Java 类加载是一个神奇的过程,因为它让我们写的代码从“静态”的文件,变成了“动态”可执行的程序。
要理解类加载,我们可以从三个主要阶段来了解它们的作用:加载、连接 和 初始化。
类加载过程的三个阶段
-
加载(Loading):
- 在这个阶段,JVM 通过类加载器(ClassLoader)找到我们写的
.class文件,把它们的字节码读进内存。 - 这个过程可以想象成打开一本书,把它从书架上取出来,放到桌子上开始阅读。
- 在这个阶段,JVM 通过类加载器(ClassLoader)找到我们写的
-
连接(Linking):
- 连接过程有三个小步骤:验证、准备 和 解析。
- 验证:JVM 检查类文件的格式是否正确,确保没有错误的字节码。
- 准备:JVM 为类的变量分配内存空间,并初始化默认值。
- 解析:JVM 把类中的符号引用(如方法名、变量名)转换成直接引用,让它们可以被实际调用。
- 类似于读书时理解内容的逻辑,比如检查章节标题和内容是不是一致。
- 连接过程有三个小步骤:验证、准备 和 解析。
-
初始化(Initialization):
- 这是类加载的最后一步。JVM 会执行类中的静态初始化代码和静态变量的赋值操作。
- 可以理解为在正式读书前标注关键内容,为阅读做准备。
一个简单的案例:类加载的工作原理
假设我们有一个简单的类 HelloWorld:
public class HelloWorld {static String message = "Hello, Java!";static {System.out.println("HelloWorld 类已被加载!");}public void sayHello() {System.out.println(message);}
}
这个 HelloWorld 类有一个静态变量 message 和一个静态代码块。静态代码块中的 System.out.println() 会在类加载时执行。
使用这个类
我们编写一个 Main 类来使用 HelloWorld:
public class Main {public static void main(String[] args) {HelloWorld hello = new HelloWorld(); // 第一次使用 HelloWorld 类hello.sayHello(); // 调用方法}
}
当我们运行 Main 类时,会看到以下输出:
HelloWorld 类已被加载!
Hello, Java!
类加载的顺序
让我们分解一下这个过程发生了什么:
-
加载:
- 当
Main类中第一次创建HelloWorld对象时,JVM 发现HelloWorld类还没有被加载。 - 类加载器加载
HelloWorld.class文件,将其加载进内存。
- 当
-
连接:
- JVM 连接
HelloWorld类,检查它的格式(验证)、为message分配内存并设置默认值(准备),然后解析类中的方法和变量引用。
- JVM 连接
-
初始化:
- JVM 执行
HelloWorld类的静态代码块System.out.println("HelloWorld 类已被加载!");,这就是我们看到的第一行输出。 - 同时,把
message静态变量赋值为"Hello, Java!"。
- JVM 执行
类加载的特点
-
延迟加载(Lazy Loading):
- Java 类的加载是延迟的,JVM 在真正使用一个类时才会加载它。这就是为什么
HelloWorld类的静态代码块在我们调用new HelloWorld()时才会执行。
- Java 类的加载是延迟的,JVM 在真正使用一个类时才会加载它。这就是为什么
-
类加载器(ClassLoader):
- Java 中有三种类加载器,分别是启动类加载器、扩展类加载器和应用类加载器。
- 启动类加载器负责加载核心 Java 类库,比如
java.lang.String。 - 扩展类加载器负责加载一些扩展类。
- 应用类加载器负责加载应用程序中定义的类,比如我们的
HelloWorld类。
- 启动类加载器负责加载核心 Java 类库,比如
- Java 中有三种类加载器,分别是启动类加载器、扩展类加载器和应用类加载器。
-
单一实例:
- 一个类在整个应用中只会被加载一次。如果我们多次创建
HelloWorld对象,静态代码块不会重复执行,这就是类加载的“单一实例”特性。
- 一个类在整个应用中只会被加载一次。如果我们多次创建
类加载的好处
类加载过程是 Java 的一个核心优势:
- 安全性:加载过程中的验证步骤帮助确保类文件不会有错误的字节码,保护程序不被恶意代码破坏。
- 效率:Java 只在需要时加载类,减少了内存占用。
- 可扩展性:类加载器机制允许动态加载类,比如在 Java Web 应用中可以动态加载第三方库。
总结
Java 类加载是一个将 .class 文件加载到内存的过程,通过加载、连接和初始化的三个步骤来确保类能够被正确地使用。类加载机制保证了代码的安全性、可维护性和内存管理的效率。理解类加载,可以帮助我们更好地使用 Java 的类和对象,让代码运行得更加流畅!
希望这个解释让你对 Java 类加载有了更清晰的认识!
推荐阅读文章
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
什么是 Cookie?简单介绍与使用方法
-
什么是 Session?如何应用?
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
如何理解应用 Java 多线程与并发编程?
-
把握Java泛型的艺术:协变、逆变与不可变性一网打尽
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
如何理解线程安全这个概念?
-
理解 Java 桥接方法
-
Spring 整合嵌入式 Tomcat 容器
-
Tomcat 如何加载 SpringMVC 组件
-
“在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
-
“避免序列化灾难:掌握实现 Serializable 的真相!(二)”
-
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
-
解密 Redis:如何通过 IO 多路复用征服高并发挑战!
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
“打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
-
Java 中消除 If-else 技巧总结
-
线程池的核心参数配置(仅供参考)
-
【人工智能】聊聊Transformer,深度学习的一股清流(13)
-
Java 枚举的几个常用技巧,你可以试着用用
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)
-
为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)
相关文章:
通俗易懂:什么是 Java 类加载?
文章目录 类加载过程的三个阶段一个简单的案例:类加载的工作原理使用这个类类加载的顺序类加载的特点类加载的好处总结推荐阅读文章 在 Java 中, 类加载是一种将我们写的 Java 类文件加载到内存中的过程,让 JVM(Java 虚拟机&…...
Dijkstra 算法的实现方案
下面是一个基于 Dijkstra 算法的实现方案,能够在 DEM(数字高程模型)数据上进行寻路,并满足以下需求: 使用 Qt C++ 编写; 规避 DEM 中的障碍物; 支持指定起点和终点; 使用 GDAL 库读取 DEM 文件; 输出路径到 TXT 文件; 输出的坐标为地理坐标(例如经纬度),而不是像…...
OpenGL 进阶系列07 - 阴影贴图(shadowmap )
一:概述: 在 OpenGL 中,Shadow Mapping(阴影贴图)是一种常用的实时阴影技术,用于渲染物体的阴影效果。这种方法通过生成光源视角下的深度贴图,再在场景渲染时使用它来判断物体是否被遮挡,从而实现阴影效果。下面是实现 Shadow Mapping 的基本步骤和相关知识。 二:绘制…...
【CAN介绍】【第一篇章】
1. CAN简介 • CAN 总线( Controller Area Network Bus )控制器局域网总线 • CAN 总线是由 BOSCH 公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域 • CAN 总线特征࿱…...
【统计子矩阵——部分前缀和+双指针】
题目 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 510; int s[N][N]; int main() {ios::sync_with_stdio(0);cin.tie(0);int n, m, k;cin >> n >> m >> k;for(int i 1; i < n; i)for(int j 1; j <…...
用正则表达式检查是IP否为内网地址
用正则表达式检查是ip否为内网地址 PHP function isIntranet($ip) {/* IPV4内网地址A 类10.0.0.0~10.255.255.255B 类172.16.0.0~172.31.255.255C 类192.168.0.0~192.168.255.255*/// 检查是否为 IPv4 内网地址if (preg_match(/^10\./, $ip…...
Leetcode刷题笔记14
136. 只出现一次的数字 136. 只出现一次的数字 - 力扣(LeetCode) 核心思想:按位异或运算 利用按位异或运算的性质来解决这个问题: 异或运算的性质: a ^ a 0:相同的数异或结果为0。 a ^ 0 a:…...
PHP图书绘本借阅管理系统小程序源码
📚 图书绘本借阅管理系统:打造孩子的阅读乐园 📚 🏷️ 引言:为什么我们需要图书绘本借阅管理系统? 在孩子的成长旅程中,阅读是不可或缺的一部分。然而,面对琳琅满目的图书和绘本&a…...
【JavaWeb】JavaWeb入门之XML详解
目录 1.XML介绍 1.1.XML概述 1.1.1.什么是XML 1.1.2.XML的作用 1.1.3.XML与HTML的比较 1.1.4.XML和properties(属性文件)比较 1.1.5.W3C组织 1.2.XML语法概述 1.2.1.XML文档展示 1.2.2.XML文档的组成部分 1.3.XML文档声明 1.3.1.什么是XML文…...
JS手写-this绑定实现
在 JavaScript 中,bind、call 和 apply 方法都可以用来改变函数的 this 指向。下面我们将分别实现这些方法的简单版本。 1. 实现 bind bind 方法创建一个新的函数,在调用时设置 this 值,并返回这个新的函数。 Function.prototype.myBind …...
【时间之外】IT人求职和创业应知【31】
目录 新闻一:2024年“秦创原沣东杯”陕西省科技工作者创新创业大赛颁奖仪式暨沣东新城机器人产业发展大会盛大启幕 新闻二:声网CEO赵斌:RTE将成为生成式AI时代AI Infra的关键部分 新闻三:“5G工业互联网”融合应用试点城市名单…...
如何使用ffmpeg命令行进行录屏
录屏软件,我们去网上下载,发现有很多软件都是要收费的!但是录屏功能很难做吗?为啥都需要收费呢? 于是我整了个小demo,用于实现基础的屏幕录制功能。 思路很简单,考虑到 FFMpeg.exe是一个非常成…...
ODOO学习笔记(8):模块化架构的优势
灵活性与可定制性 业务流程适配:企业的业务流程往往因行业、规模和管理方式等因素而各不相同。Odoo的模块化架构允许企业根据自身的具体业务流程,选择和组合不同的模块。例如,一家制造企业可以启用采购、库存、生产和销售模块,并通…...
数字IC后端实现之Innovus specifyCellEdgeSpacing和ICC2 set_placement_spacing_rule的应用
昨天帮助社区IC训练营学员远程协助解决一个Calibre DRC案例。通过这个DRC Violation向大家分享下Innovus和ICC2中如何批量约束cell的spacing rule。 数字IC后端手把手实战教程 | Innovus verify_drc VIA1 DRC Violation解析及脚本自动化修复方案 下图所示为T12nm A55项目的Ca…...
每日小练:Day2
1.乒乓球筐 题目链接:乒乓球筐__牛客网 题目描述: 这道题主要考察B盒是不是A盒的子集,我们可以通过哈希表来做 单哈希表 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public stat…...
ubuntu 安装kafka-eagle
上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群 /root/efak 目录 cd /root/efak tar -zxvf kafka-eagle-bin-2.0.8.tar.gz cd /root/efak/kafka-eagle-bin-2.0.8 mkdir /root/efakmodule tar -zxvf efak-web-2.0.8-bin.tar.gz -C /root/efakmodule/ mv /root/efakmodule/efak…...
深入理解指针
在初步了解了指针的用法之后,我们可以想一想,既然一个变量有地址,而且在上一篇文章中我们知道了一个数组也有地址,那么函数、字符串这些东西有没有地址呢?如果有,那这些地址有什么用?我们又要怎…...
自动驾驶合集(更新中)
文章目录 车辆模型控制路径规划 车辆模型 车辆模型基础合集 控制 控制合集 路径规划 规划合集...
Chapter 14 scoped样式以及data函数
欢迎大家订阅【Vue2Vue3】入门到实践 专栏,开启你的 Vue 学习之旅! 文章目录 1 scoped样式1.1 全局样式1.2 局部样式1.3 工作原理2 data函数 1 scoped样式 1.1 全局样式 全局样式是指作用于整个应用程序的样式,不论在哪个组件中定义&#x…...
Golang | Leetcode Golang题解之第557题反转字符串中的单词III
题目: 题解: func reverseWords(s string) string {length : len(s)ret : []byte{}for i : 0; i < length; {start : ifor i < length && s[i] ! {i}for p : start; p < i; p {ret append(ret, s[start i - 1 - p])}for i < le…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
