当前位置: 首页 > article >正文

通俗易懂:什么是 Java 类加载?

文章目录

      • 类加载过程的三个阶段
      • 一个简单的案例:类加载的工作原理
      • 使用这个类
      • 类加载的顺序
      • 类加载的特点
      • 类加载的好处
      • 总结
      • 推荐阅读文章

在 Java 中, 类加载是一种将我们写的 Java 类文件加载到内存中的过程,让 JVM(Java 虚拟机)可以识别和执行它们。Java 类加载是一个神奇的过程,因为它让我们写的代码从“静态”的文件,变成了“动态”可执行的程序。

要理解类加载,我们可以从三个主要阶段来了解它们的作用:加载连接初始化


类加载过程的三个阶段

  1. 加载(Loading)

    • 在这个阶段,JVM 通过类加载器(ClassLoader)找到我们写的 .class 文件,把它们的字节码读进内存。
    • 这个过程可以想象成打开一本书,把它从书架上取出来,放到桌子上开始阅读。
  2. 连接(Linking)

    • 连接过程有三个小步骤:验证准备解析
      • 验证:JVM 检查类文件的格式是否正确,确保没有错误的字节码。
      • 准备:JVM 为类的变量分配内存空间,并初始化默认值。
      • 解析:JVM 把类中的符号引用(如方法名、变量名)转换成直接引用,让它们可以被实际调用。
    • 类似于读书时理解内容的逻辑,比如检查章节标题和内容是不是一致。
  3. 初始化(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!

类加载的顺序

让我们分解一下这个过程发生了什么:

  1. 加载

    • Main 类中第一次创建 HelloWorld 对象时,JVM 发现 HelloWorld 类还没有被加载。
    • 类加载器加载 HelloWorld.class 文件,将其加载进内存。
  2. 连接

    • JVM 连接 HelloWorld 类,检查它的格式(验证)、为 message 分配内存并设置默认值(准备),然后解析类中的方法和变量引用。
  3. 初始化

    • JVM 执行 HelloWorld 类的静态代码块 System.out.println("HelloWorld 类已被加载!");,这就是我们看到的第一行输出。
    • 同时,把 message 静态变量赋值为 "Hello, Java!"

类加载的特点

  1. 延迟加载(Lazy Loading)

    • Java 类的加载是延迟的,JVM 在真正使用一个类时才会加载它。这就是为什么 HelloWorld 类的静态代码块在我们调用 new HelloWorld() 时才会执行。
  2. 类加载器(ClassLoader)

    • Java 中有三种类加载器,分别是启动类加载器扩展类加载器应用类加载器
      • 启动类加载器负责加载核心 Java 类库,比如 java.lang.String
      • 扩展类加载器负责加载一些扩展类。
      • 应用类加载器负责加载应用程序中定义的类,比如我们的 HelloWorld 类。
  3. 单一实例

    • 一个类在整个应用中只会被加载一次。如果我们多次创建 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 的“暗坑”与解决方案(二)


http://www.kler.cn/a/393779.html

相关文章:

  • SystemVerilog学习笔记(六):控制流
  • 相机光学(四十二)——sony的HDR技术
  • 如何从头开始构建神经网络?(附教程)
  • three.js 杂记
  • 普通电脑上安装属于自己的Llama 3 大模型和对话客户端
  • 【AI大模型】ELMo模型介绍:深度理解语言模型的嵌入艺术
  • 多叉树笔记
  • Linux 如何使用函数删除非空目录
  • Android11 修改系统语言
  • P10901 [蓝桥杯 2024 省 C] 封闭图形个数
  • scala创建图书信息类,包含三个属性:书名,作者,价格
  • Spring Boot框架:电商系统的快速开发
  • arcgis做buffer
  • 学习threejs,使用导入的模型生成粒子
  • 扫雷游戏代码分享(c基础)
  • 观察者模式 vs 不使用观察者模式:商品库存变化的通知
  • Spring框架之责任链模式 (Chain of Responsibility Pattern)
  • GDSC、CTRP数据库学习
  • ApiSmart-QWen2.5 coder vs GPT-4o 那个更强? ApiSmart 测评
  • 使用Java爬虫获取淘宝商品类目API返回值
  • Rust学习(一):初识Rust和Rust环境配置
  • Kafka Eagle 安装教程
  • ue5 蓝图学习(一)结构体的使用
  • 什么是 WPF 中的转换器?如何自定义一个值转换器?
  • 06-form-serialize插件的使用、案例
  • redis实现消息队列的几种方式