通俗易懂:什么是 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…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...

Python环境安装与虚拟环境配置详解
本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南,适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者,都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...