news 2026/6/10 20:10:48

Java类加载机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java类加载机制

Java 类加载机制详解

Java 类加载机制是 JVM(Java 虚拟机)的核心组成部分,负责将编译后的.class文件(字节码)从磁盘、网络或其他来源加载到内存中,并转换为可执行的 Java 类对象。整个过程遵循双亲委派模型,确保安全性和一致性。

1. 类加载的生命周期(Class Lifecycle)

一个类从加载到卸载,主要经历以下 5 个阶段:

  1. 加载(Loading)

    • 查找并读取字节码文件(.class),通过类加载器将字节码加载到 JVM 的方法区(JDK 8 前是永久代,JDK 8+ 是元空间)。
    • 生成对应的java.lang.Class对象(在堆中)。
  2. 连接(Linking)

    • 验证(Verification):确保字节码的安全性(格式、指令合法性等),防止恶意代码。
    • 准备(Preparation):为类的静态变量分配内存,并设置默认初始值(int=0, boolean=false, 引用=null 等)。
    • 解析(Resolution):将常量池中的符号引用转换为直接引用(可选,延迟解析)。
  3. 初始化(Initialization)

    • 执行类的静态初始化代码:静态变量赋值 + 静态代码块。
    • 初始化发生在类首次主动使用时(如 new、访问静态成员、反射等)。
    • <clinit>方法(编译器自动生成)。
  4. 使用(Using)

  5. 卸载(Unloading)

    • 当类不再被任何对象引用,且类加载器也被回收时,由 GC 卸载(自定义类加载器才可能被卸载)。
2. 类加载器(ClassLoader)

Java 默认使用三层类加载器(Bootstrap + Extension + Application),构成层次结构:

类加载器名称加载路径特点
Bootstrap ClassLoader(启动类加载器)$JAVA_HOME/lib中的核心类库(如 rt.jar:Object、String、System 等)用 C++ 实现,无 Java 对象引用(null)
Extension ClassLoader(扩展类加载器)$JAVA_HOME/lib/ext目录下的 jar父是 Bootstrap
Application ClassLoader(应用类加载器,也称 System ClassLoader)classpath 指定的路径(项目中的 classes、依赖 jar)父是 Extension,通常加载我们写的代码

此外还有:

  • 自定义类加载器:继承ClassLoader,重写findClass()方法。
  • 线程上下文类加载器(Thread Context ClassLoader):用于打破双亲委派(如 SPI 机制:JDBC、Servlet 容器)。
3. 双亲委派模型(Parental Delegation Model)

这是 Java 类加载机制的核心设计,工作流程:

  1. 当一个类加载器收到类加载请求时,不会自己先尝试加载
  2. 而是将请求向上委托给父类加载器(递归)。
  3. 只有当父类加载器无法找到该类时,当前类加载器才会尝试自己加载。

优点

  • 安全性:防止用户自定义恶意类覆盖核心类(如自定义 java.lang.String)。
  • 避免重复加载:同一个类只会被加载一次(由最高层的加载器加载)。
  • 命名空间隔离:不同类加载器加载的同名类是不同的(Class 对象不同)。

打破双亲委派的情况

  • 重写loadClass()方法(不推荐)。
  • SPI 机制(Service Provider Interface):如 JDBC DriverManager 使用线程上下文类加载器加载驱动。
  • 模块化系统(Java 9+ 的模块路径)。
  • 应用容器(如 Tomcat、Spring Boot)实现隔离。
4. 类加载的触发时机(首次主动使用)

以下操作会触发类初始化(执行<clinit>):

  • new创建对象
  • 访问静态变量或静态方法(包括赋值)
  • 反射:Class.forName("com.test.MyClass")(默认初始化,可传 false 跳过)
  • 初始化子类时,先初始化父类
  • 启动类(包含 main 方法的类)被加载时
  • 使用java.lang.invoke.MethodHandle的 REF_getStatic 等

不会触发初始化的情况

  • 访问常量(编译期常量,如 final static int A = 5)
  • 子类访问父类的静态字段(只初始化父类)
  • Class.forName("xxx", false, loader)
5. 示例代码演示
classParent{static{System.out.println("Parent static block");}publicstaticintvalue=100;}classChildextendsParent{static{System.out.println("Child static block");}}publicclassTest{publicstaticvoidmain(String[]args){System.out.println(Child.value);// 输出:Parent static block → 100// Child static block 不会执行,因为 Child 类未被主动使用}}
6. 常见面试题
  • 一个类会被加载几次?
    正常情况下只加载一次(由某个类加载器加载)。

  • 如何打破双亲委派?
    自定义类加载器,重写loadClass(),或使用线程上下文类加载器。

  • Tomcat 如何实现 Web 应用隔离?
    每个 Web 应用使用独立的 WebappClassLoader,优先加载本应用的类,打破双亲委派。

  • 为什么 String 类不能被自定义覆盖?
    因为它由 Bootstrap ClassLoader 加载,用户自定义的 String 在不同命名空间。

总结

Java 类加载机制的核心是:

  • 生命周期:加载 → 连接(验证+准备+解析) → 初始化 → 使用 → 卸载
  • 双亲委派模型:安全 + 避免重复加载
  • 类加载器层次:Bootstrap → Extension → Application → 自定义

理解类加载机制对深入掌握 JVM、Spring 容器、热部署、插件化开发至关重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 20:01:12

如何用 Yuer DSL 构建一个投资风险量化前置裁决模板

1. 背景&#xff1a;问题不在“算得准不准”&#xff0c;而在“该不该开始算”在 EDCA OS / Yuer DSL 的多轮高责任场景测试中&#xff0c;我们发现一个在工程实践中反复出现的问题&#xff1a;多数 AI 投资系统的风险&#xff0c;并不源于模型能力不足&#xff0c; 而源于 在信…

作者头像 李华
网站建设 2026/6/7 22:52:49

AI 量化为什么不敢上线?——我的 Fail-Closed 模板实战

很多人私下问过我一个问题&#xff1a;“AI 都已经能写策略、跑回测、算因子了&#xff0c; 为什么真正能上线跑真金白银的系统&#xff0c;反而很少&#xff1f;”这个问题&#xff0c;其实不在模型能力上&#xff0c; 而在上线这一步&#xff0c;谁敢签字。一、AI 量化“不敢…

作者头像 李华
网站建设 2026/6/10 16:00:20

欧盟EN 18031-1无线设备认证

对于计划进军欧盟市场的无线设备制造商来说&#xff0c;EN 18031-1已成为绕不开的合规门槛。自2025年8月1日正式强制执行以来&#xff0c;不少企业因对标准细节理解偏差&#xff0c;遭遇了产品扣留、测试反复等问题&#xff1a;有的误将旧版EN 303645证书当作豁免依据&#xff…

作者头像 李华
网站建设 2026/6/10 13:00:05

【ITK手册003】深入理解 itk::SmartPointer:医疗影像开发的内存基石

【ITK手册003】深入理解 itk::SmartPointer&#xff1a;医疗影像开发的内存基石 1. 概括 在基于 ITK (Insight Toolkit) 的医学图像处理软件开发中&#xff0c;内存管理是维持系统稳定性的关键。itk::SmartPointer<T> 是 ITK 实现自动内存管理的核心机制。它通过侵入式…

作者头像 李华
网站建设 2026/6/10 14:11:57

三菱FX3U + 485ADP MB与台达MS300变频器通讯程序分享

三菱FX3U485ADP MB与台达MS300变频器通讯程序 功能&#xff1a;通过三菱fx3u 485ADP-MB板对台达ms300变频器进行modbus通讯&#xff0c;实现频率设定&#xff0c;启停控制&#xff0c;输出频率读取&#xff0c;输出电压读取。 配件&#xff1a;三菱fx3u 485ADP-mb&#xff0c;三…

作者头像 李华