JVM 类加载 详解

JVM 类加载详解

JVM 类加载(Java Class Loading) 是 Java 虚拟机 (JVM) 执行 Java 程序的重要机制之一,用于将 .class 文件动态加载到内存中并进行验证、解析和初始化,最终生成可以直接使用的类对象。


1. 类加载的基本概念

1.1 什么是类加载?

类加载是将 .class 文件加载到 JVM 并转化为内存中可以运行的类的过程。

  • 目标:生成一个内存中的 Class 对象,供程序使用。
  • 触发点
    • 当程序首次访问类或接口时(如创建对象、访问静态字段或调用静态方法)。
    • 通过反射加载类(如 Class.forName)。
    • 动态代理生成的类。

1.2 类加载的三阶段

  1. 加载(Loading):
    • .class 文件加载到内存中,生成 Class 对象。
  2. 链接(Linking):
    • 将类的二进制数据合并到 JVM 中。
      • 验证:检查类文件的合法性。
      • 准备:为类的静态变量分配内存,并设置默认初始值。
      • 解析:将类、方法、字段的符号引用解析为直接引用。
  3. 初始化(Initialization):
    • 执行类的初始化逻辑,包括静态变量的赋值和静态代码块的执行。

2. JVM 类加载机制

JVM 的类加载遵循 双亲委派模型运行时动态加载 的原则。

2.1 双亲委派模型

定义

类加载时会先委托父加载器加载,只有当父加载器无法加载时,才由当前加载器尝试加载。

过程
  1. 一个类加载请求从当前类加载器开始。
  2. 如果当前加载器存在父加载器,优先交给父加载器处理。
  3. 如果父加载器无法加载,则由当前加载器加载。
优点
  • 安全性:防止重复加载,保证核心类不被篡改。
  • 统一性:确保 Java 的基础类库(如 java.lang.String)使用同一个加载器加载。

2.2 类加载器

JVM 的主要类加载器
  1. 启动类加载器(Bootstrap ClassLoader)

    • 负责加载 JVM 的核心类库,如 rt.jar
    • 用 C/C++ 实现,直接由 JVM 内部调用。
  2. 扩展类加载器(Extension ClassLoader)

    • 加载 JAVA_HOME/lib/ext 目录下的扩展类库。
  3. 应用类加载器(App ClassLoader)

    • 加载应用程序的类路径(CLASSPATH)下的类。
  4. 自定义类加载器(Custom ClassLoader)

    • 用户可以通过继承 ClassLoader 自定义类加载器。
类加载器之间的关系
  • 启动类加载器是最顶层的加载器,扩展类加载器和应用类加载器是其子加载器。
  • 自定义类加载器通常由应用类加载器加载。

3. 类加载的流程

以下是类加载的主要流程及每个阶段的作用:

3.1 加载阶段

  • 功能:将 .class 文件加载到内存中,生成 Class 对象。
  • 操作
    1. 通过类的全限定名找到对应的 .class 文件。
    2. .class 文件的字节流读入内存。
    3. 将字节流解析为 Class 对象。

3.2 链接阶段

  1. 验证

    • 确保 .class 文件符合 Java 规范,保证字节码的合法性。
    • 检查:
      • 魔数和版本号。
      • 常量池中符号的正确性。
      • 字节码指令是否正确。
  2. 准备

    • 为静态变量分配内存,并设置默认初始值(如 0null)。
    • 示例:
      public static int a = 10;
      
      在准备阶段,a 的值为 0,赋值为 10 在初始化阶段完成。
  3. 解析

    • 将常量池中的符号引用(如方法名、字段名)替换为直接引用(内存地址)。

3.3 初始化阶段

  • 触发点
    • 主动使用类(如实例化对象、调用静态方法)。
  • 操作
    • 初始化静态变量。
    • 执行静态代码块。

4. 类加载的类型

根据触发类加载的时机,类加载分为以下两种类型:

4.1 主动引用

以下情况会触发类的加载:

  1. 创建类的实例。
  2. 访问类的静态字段。
  3. 调用类的静态方法。
  4. 通过反射调用类。
  5. 初始化类的子类。

示例:

class Demo {static {System.out.println("Demo类被初始化");}
}
public class Main {public static void main(String[] args) {Demo demo = new Demo(); // 主动触发}
}

4.2 被动引用

以下情况不会触发类的加载:

  1. 通过子类调用父类的静态字段。
  2. 定义类的数组。
  3. 引用类的常量。

示例:

class Parent {static {System.out.println("Parent类被初始化");}public static int value = 42;
}class Child extends Parent {static {System.out.println("Child类被初始化");}
}public class Main {public static void main(String[] args) {System.out.println(Child.value); // 只触发父类加载}
}

5. 类加载的关键点

5.1 类加载器的双亲委派机制

  • 原理:父加载器优先加载,确保基础类不被重复加载。
  • 示例
ClassLoader loader = Demo.class.getClassLoader();
System.out.println(loader);                   // AppClassLoader
System.out.println(loader.getParent());       // ExtClassLoader
System.out.println(loader.getParent().getParent()); // null (Bootstrap)

5.2 自定义类加载器

  • 自定义类加载器通常用于加载加密的类文件或特殊格式的类文件。

实现示例

public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = loadClassData(name);return defineClass(name, classData, 0, classData.length);}private byte[] loadClassData(String name) {// 加载类文件的字节流return new byte[0]; // 示例中省略实际加载逻辑}
}

6. 类加载的示例

6.1 静态字段与静态代码块

class Demo {static int value = 10;static {System.out.println("静态代码块执行");value = 20;}
}
public class Main {public static void main(String[] args) {System.out.println(Demo.value); // 输出: 静态代码块执行 20}
}

6.2 动态加载类

public class Main {public static void main(String[] args) throws Exception {Class<?> clazz = Class.forName("com.example.Demo");Object obj = clazz.getDeclaredConstructor().newInstance();System.out.println(obj.getClass().getName());}
}

7. 类加载的优缺点

7.1 优点

  1. 延迟加载:提高系统启动效率。
  2. 动态扩展:支持动态加载类,增强灵活性。
  3. 隔离性:不同的类加载器可以隔离命名空间,避免冲突。

7.2 缺点

  1. 性能开销:加载类时需要额外的资源。
  2. 复杂性:双亲委派机制增加调试难度。

8. 总结

  • 核心机制:类加载是 JVM 将 .class 文件转化为可运行代码的关键环节,主要包括加载、链接和初始化三阶段。
  • 双亲委派模型:确保类加载的安全性和统一性。
  • 动态性:支持运行时加载和动态代理等功能。
  • 实际应用:常见于自定义类加载器、插件系统和框架设计中。

深入理解类加载机制,可以
帮助开发者更好地调优 JVM,设计更灵活的应用程序。

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

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

相关文章

AWS账号提额

Lightsail提额 控制台右上角&#xff0c;用户名点开&#xff0c;选择Service Quotas 在导航栏中AWS服务中找到lightsail点进去 在搜索框搜索instance找到相应的实例类型申请配额 4.根据自己的需求选择要提额的地区 5.根据需求来提升配额数量,提升小额配额等大约1小时生效 Ligh…

LCD与lvgl

LCD与lvgl 目录 LCD与lvgl 回顾 LCD 的驱动层讲解 1、LCD 的常见接口 2、我们的 LCD 的参数 3、LCD 的设备树说明 4、LCD 的设备树说明 5、如何移植 LCD 的驱动(重点) LCD 的应用层开发 1&#xff1a;LCD 应用开发->界面开发的方法 2&#xff1a;LVGL 模拟器安装…

Linux -初识 与基础指令2

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【Linux】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f4da; 前言&#x1f511; 概念一&#x1f511; 概念二 &#x1f4d6; man&#x1f4ac; echo&#x1f4c1; cp&#x1f4c2; mv&#x1f511; 概念三&am…

HCIE IGP双栈综合实验

实验拓扑 实验需求及解法 本实验模拟ISP网络结构&#xff0c;R1/2组成国家骨干网&#xff0c;R3/4组成省级网络&#xff0c;R5/6/7组成数据中 心网络。 配置所有ipv4地址&#xff0c;请自行测试直连。 R1 sysname R1 interface GigabitEthernet0/0/0ip address 12.1.1.1 255.…

大模型微调论文阅读 LoRA:LOW-RANK ADAPTION OF LARGE LANGUAGE MODELS 大型语言模型的低秩自适应

论文link&#xff1a;https://arxiv.org/pdf/2106.09685 code&#xff1a;https://github.com/microsoft/LoRA LoRA&#xff1a;Low-Rank Adaptation of Large Language Models Abstract 自然语言处理的一个重要范例是对通用领域数据进行大规模预训练&#xff0c;并适应特定任…

Ubuntu24.04配置DINO-Tracker

一、引言 记录 Ubuntu 配置的第一个代码过程 二、更改conda虚拟环境的默认安装路径 鉴于不久前由于磁盘空间不足引发的重装系统的惨痛经历&#xff0c;在新系统装好后当然要先更改虚拟环境的默认安装路径。 输入指令&#xff1a; conda info可能因为我原本就没有把 Anacod…

Python 深度学习框架之Keras库详解

文章目录 Python 深度学习框架之Keras库详解一、引言二、Keras的特点和优势1、用户友好2、多网络支持3、跨平台运行 三、Keras的安装和环境配置1、软硬件环境2、Python虚拟环境 四、使用示例1、MNIST手写数字识别 五、总结 Python 深度学习框架之Keras库详解 一、引言 Keras是…

电机参数辨识算法(3)——基于三角波电流注入的SPMSM全参数辨识策略

1.引言 电机参数辨识对提高电机控制性能具有重要意义。在之前的参数辨识专题中&#xff0c;介绍了基于无差拍预测电流控制的高频正弦电流注入参数辨识。高频正弦电流注入的话需要你控制器的带宽比较高&#xff0c;因此这种方法不适用于传统PI控制的电流环&#xff0c;还是得用…

Vulnhub靶场 Matrix-Breakout: 2 Morpheus 练习

目录 0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用1. 文件上传2. 提权 0x04 总结 0x00 准备 下载连接&#xff1a;https://download.vulnhub.com/matrix-breakout/matrix-breakout-2-morpheus.ova 介绍&#xff1a; This is the second in the Matrix-Br…

HTML5动漫主题网站——天空之城 10页 html+css+设计报告成品项目模版

&#x1f4c2;文章目录 一、&#x1f4d4;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站演示 五、⚙️网站代码 &#x1f9f1;HTML结构代码 &#x1f492;CSS样式代码 六、&#x1f527;完整源码下载 七、&#x1f4e3;更多 一、&#…

SpringMVC:入门案例

从此开始&#xff0c;我们步入SpringMVC的学习。 SpringMVC是一种基于Java实现MVC模型的轻量级Web框架 先来看一下web程序是如何工作的&#xff1a; 因为是异步调用&#xff0c;所以后端不需要返回view视图&#xff0c;将其去除前端如果通过异步调用的方式进行交互&#xff0…

【Windows 11专业版】使用问题集合

博文将不断学习补充 I、设置WIN R打开应用默认使用管理员启动 1、WIN R输入 secpol.msc 进入“本地安全策略”。 2、按照如下路径&#xff0c;找到条目&#xff1a; “安全设置”—“本地策略”—“安全选项”—“用户账户控制&#xff1a;以管理员批准模式运行所有管理员” …

Python学习38天

class Person:def __init__(self, name, age, job):self.name nameself.age ageself.job job# 重写函数返回属性def __str__(self):return f"{self.name}--{self.age}--{self.job}"# 冒泡排序法 def bubble_sort(my_list: list[Person]):"""冒泡排…

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本。 原因是&#xff1a;当前操作系统版本为Windows Server 2016 Standard版本&#xff0c;其自带的Microsoft .NET Framework 版本为4.6太低&#xff0c;不满足要求。 根据报错的提示&#xff0c;点击链接…

鸿蒙开发:自定义一个任意位置弹出的Dialog

前言 鸿蒙开发中&#xff0c;一直有个问题困扰着自己&#xff0c;想必也困扰着大多数开发者&#xff0c;那就是&#xff0c;系统提供的dialog自定义弹窗&#xff0c;无法实现在任意位置进行弹出&#xff0c;仅限于CustomDialog和Component struct的成员变量&#xff0c;这就导致…

DTC控制,直接转矩控制详解

关于磁链矢量所在扇区及最优开关表的选择的思路分析和matlab/simulink实现 仿真参考袁雷老师的《现代永磁同步电机控制原理及MATLAB仿真》&#xff0c;但是由于书中所附代码和书中第四章中讲的实现不同&#xff0c;因此根据自己看的资料和理解重新整理并实现了一下。 这里采用…

css选择当前元素前面的一个元素

选择text-danger前面的ant-divider: .ant-divider:has( .text-danger) {display: none; }

Qt,如何从零开始入门!

Qt 是一个功能全面的跨平台开发框架&#xff0c;不仅可以用于开发桌面应用&#xff0c;还在嵌入式系统中扮演重要角色。即使没有图形化 IDE&#xff08;如 Qt Creator&#xff09;&#xff0c;你依然可以使用命令行工具和文本编辑器来快速构建功能强大的应用程序。本文将从手动…

oracle数据库的启动与关闭

一.oracle数据库的启动过程 启动实例&#xff08;Start the Instance&#xff09; 启动实例&#xff1a;一个Oracle数据库实例由内存结构和后台进程组成&#xff0c;启动实例时会加载这些内存结构和启动进程。实例是数据库的一个运行时环境&#xff0c;它包含了数据库的控制文…

最新版Chrome浏览器调用ActiveX控件之allWebOffice控件

allWebOffice控件概述 allWebOffice控件能够实现在浏览器窗口中在线操作微软Office及WPS办公文档的应用&#xff08;阅读、编辑、保存等&#xff09;&#xff0c;支持编辑文档时保留修改痕迹&#xff0c;支持书签位置内容动态填充&#xff0c;支持公文套红&#xff0c;支持文档…