urlname
type
Post
password
SyncToConfluence
category
学习笔记
date
Apr 13, 2024
slug
01HV9NP1YQAFWF4JEEY83CHV72
icon
Button
catalog
summary
tags
JVM
Java
cover
Status
BusyTime
Status 1
status
Published
Java类的加载过程是Java虚拟机(JVM)进行类处理的一个核心部分,涉及到将类的.class文件从磁盘加载到内存,并为之准备运行环境的一系列步骤。
Java类的加载、链接和初始化过程严格规定了各个步骤的执行顺序,确保Java程序能正确运行。
Java类加载过程
加载-Loading
- 职责
- 将.class文件,加载进JVM,并创建
Class对象。
- 作用:
- 将类的.class文件中的原始字节流转换为方法区中的运行时数据结构。
- 在Java堆中创建一个Class对象,作为方法区这些数据的访问入口。
- 关键组件:
- 类加载器
- 涉及内容:
- 类加载器(如Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader及用户自定义类加载器)。
- Class文件格式。
- 二进制字节流到JVM内部结构的映射。
链接-Linking
- 职责:
- 验证类的正确性,为类变量分配内存,并解析该类创建的符号引用到具体的内存地址中。
- 作用:
- 确保类在JVM中正确、安全地布局。
- 将内存中的符号引用替换为可以直接由JVM使用的地址或指针。
- 三个阶段:
- 验证(Verification):验证加载的类是否符合JVM规范。
- 准备(Preparation):为类变量分配内存,并设置默认初始化值。
- 解析(Resolution):将符号引用转化为直接引用。
- 涉及内容:
- 类和接口的解析。
- Java虚拟机规范中的数据类型和结构。
- 内存管理和符号表。
初始化-Initialization
- 职责:
- 执行静态初始化器和静态初始化块。
- 对类进行初始化,执行类构造器方法。
- 作用:
- 初始化类变量。
- 涉及内容:
- Java内存模型(JMM)。
- 类的生命周期。
相关问题
为什么需要不同的类加载器
- 隔离:不同的类加载器可以用于加载不同来源的代码,从而保证了运行时环境的安全性和类之间的隔离,防止类的名称冲突。
- 安全性:系统类和应用类使用不同的加载器,可以防止恶意代码替换核心的API类,增强JVM的安全性。
- 灵活性:允许从各种来源动态加载类,如从网络、动态生成的代码或其他文件格式。
不同类加载器之间的关系
类加载器有一个父子层级关系,类似一个树形结构。类加载器可以被分为以下几种:
- 启动类加载器(Bootstrap ClassLoader):
- 虚拟机的内置类加载器,负责加载Java的核心库(如
rt.jar、resources.jar等JRE的核心类库)。 - 启动类加载器是用原生代码实现的,并不继承自
java.lang.ClassLoader。
- 扩展类加载器(Extension ClassLoader):
- 从JDK的扩展目录(
jre/lib/ext或者由系统属性java.ext.dirs指定的任何目录)加载类库。 - 是
java.lang.ClassLoader的子类,其父加载器是启动类加载器。
- 应用程序类加载器(Application ClassLoader):
- 类加载器架构中的默认类加载器,用于加载来自应用程序类路径(Classpath,环境变量中设置的)的类。
- 父加载器是扩展类加载器。
- 用户自定义加载器:
- 继承自
java.lang.ClassLoader的加载器,用于特定的加载需求,如从网络或加密存储中加载类。
类加载器的加载原则
- 双亲委托机制:
- 当一个类加载器收到类加载的请求时,它首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器去完成。
- 只有当父加载器无法完成这个请求时(它不认识这个类),子加载器才会尝试自己去加载。
- 可见性:
- 子加载器可以访问父加载器加载的类,而父加载器则不能访问子加载器加载的类。
- 单一性:
- 由同一个类加载器加载的类在JVM中只有一个唯一实例
- 这也是JVM保证加载的类在JVM内部的唯一性的方式。
没有被实例化的类,会被类加载器加载吗?
不一定,类的加载通常是因为要首次使用该类,而“使用”可以有多种形式,不限于实例化。
以下是触发类加载的几种常见情况:
- 创建实例
- 访问静态成员:访问类的静态字段或调用类的静态方法也会触发类的加载。
- 反射:使用反射API如
Class.forName("com.example.MyClass")来动态加载类,无论是否创建实例。
- 继承:当一个类被另一个类继承,父类将被加载(如果尚未加载)。即使子类没有被实例化,父类也需要加载以解析类的结构。
- 使用类或接口:直接使用类或接口来定义引用变量。
- Author:CoderWdd
- URL:https://www.wuinsights.top//article/01HV9NP1YQAFWF4JEEY83CHV72
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!