关于JVM类加载机制,看这一篇就够了(一)类加载机制

article/2025/9/22 2:30:21

1.类加载机制

1.1概述

​ Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。

​ 在Java语言里面,类型的加载、连接和初始化过程都是在程序运行期间完成的,这种策略让Java语言进行提前编译会面临额外的困难,也会让类加载时稍微增加一些性能开销,但是却为Java应用提供了极高的扩展性和灵活性。

1.2类加载的时机

​ 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称为连接(Linking)。这七个阶段的发生顺序如图7-1所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v93CJabA-1630314300805)(C:\Users\CoolGuy\AppData\Roaming\Typora\typora-user-images\image-20210825171258493.png)]

​ 加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类型的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定特性(也称为动态绑定或晚期绑定)。

​ 请注意,这里是指按部就班地“开始”,而不是按部就班地“进行”或按部就班地“完成”,强调这点是因为这些阶段通常都 是互相交叉地混合进行的,会在一个阶段执行的过程中调用、激活另一个阶段。

对于初始化阶段,《Java虚拟机规范》 则是严格规定了有且只有六种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之 前开始):

  1. 遇到new、getstatic、putstatic或invokestatic这四条字节码指令时,如果类型没有进行过初始 化,则需要先触发其初始化阶段。
  2. 使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需要先触发其初始化。
  3. 当初始化类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
  5. 当使用JDK 7新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄,并且这个方法句柄对应的类没有进行过初始化,则需要先触发其初始化。
  6. 当一个接口中定义了JDK 8新加入的默认方法(被default关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,那该接口要在其之前被初始化。

​ 对于这六种会触发类型进行初始化的场景,《Java虚拟机规范》中使用了一个非常强烈的限定语 ——“有且只有”,这六种场景中的行为称为对一个类型进行主动引用。除此之外,所有引用类型的方 式都不会触发初始化,称为被动引用

被动引用的例子

class SuperClass {static { System.out.println("SuperClass init!"); }public static int value = 123;
}
class SubClass extends SuperClass {static { System.out.println("SubClass init!");}
}/*** 非主动使用类字段演示 **/
public class Passive_reference_1 {public static void main(String[] args) {System.out.println(SubClass.value);}
}

​ 输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7R1uMjD7-1630314300808)(C:\Users\CoolGuy\AppData\Roaming\Typora\typora-user-images\image-20210825173008583.png)]

​ 解析:

上述代码运行之后,只会输出“SuperClass init!”,而不会输出“SubClass init!”。对于静态字段, 只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发 父类的初始化而不会触发子类的初始化。

2.类加载的过程

​ 接下来我们会详细了解Java虚拟机中类加载的全过程,即加载、验证、准备、解析和初始化这五个阶段所执行的具体动作。

2.1加载

​ “加载”(Loading)阶段是整个“类加载”(Class Loading)过程中的一个阶段。在加载阶段,Java虚拟机需要完成以下三件事情:

​ 1)通过一个类的全限定名来获取定义此类的二进制字节流。

​ 2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

​ 3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

​ 《Java虚拟机规范》对这三点要求其实并不是特别具体,留给虚拟机实现与Java应用的灵活度都是相当大的。例如“通过一个类的全限定名来获取定义此类的二进制字节流”这条规则,它并没有指明二进制字节流必须得从某个Class文件中获取,确切地说是根本没有指明要从哪里获取、如何获取。而由其他文件生成的例子中最典型的就是JSP文件。

2.2验证

​ 验证是连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。 验证阶段大致上会完成下面四个阶段的检验动作:文件格式验证、元数据验证、字节码验证和符号引用验证。

  • 文件格式验证

    第一阶段要验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。

  • 元数据验证

    第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合《Java语言规范》的要求.

  • 字节码验证

    第三阶段是整个验证过程中最复杂的一个阶段,主要目的是通过数据流分析和控制流分析,确定程序语义是合法的、符合逻辑的。

  • 符号引用验证

    最后一个阶段的校验行为发生在虚拟机将符号引用转化为直接引用[3]的时候,这个转化动作将在连接的第三阶段——解析阶段中发生。

2.3准备

​ 准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段,从概念上讲,这些变量所使用的内存都应当在方法区中进行分配,但必须注意到方法区本身是一个逻辑上的区域。

2.4解析

​ 解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。

​ ~符号引用(Symbolic References):符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定是已经加载到虚拟机内存当中的内容。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须都是一致的,因为符号引用的字面量形式明确定义在《Java虚拟机规范》的Class文件格式中。

​ ~直接引用(Direct References):直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。直接引用是和虚拟机实现的内存布局直接相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经在虚拟机的内存中存在。

解析动作主要针对类或接口字段类方法接口方法方法类型方法句柄调用点限定符这7类符号引用进行。

2.5初始化

​ 类的初始化阶段是类加载过程的最后一个步骤,之前介绍的几个类加载的动作里,除了在加载阶段用户应用程序可以通过自定义类加载器的方式局部参与外,其余动作都完全由Java虚拟机来主导控制。直到初始化阶段,Java虚拟机才真正开始执行类中编写的Java程序代码,将主导权移交给应用程序。


http://chatgpt.dhexx.cn/article/OXWF3fyO.shtml

相关文章

深入理解jvm类加载机制

本文将以四个问题展开: 什么是类加载?什么是双亲委任模型?如何破坏双亲委任模型?Tomcat 的类加载器是怎么设计的? 1.什么是类加载? 类加载机制一个很大的体系,包括类加载的时机,类…

从JDK源码级别彻底刨析JVM类加载机制

当我们用java命令运行某个类的main函数启动程序时,大家有没有想过是怎样加载的,本文将带着大家一起探讨JVM类的加载机制类加载运行全过程 请看下方代码: package com.bethmeta.jvm; public class Math {public static final int initData 6…

讲透JVM类加载机制,向高手进阶!

目录: 前言JVM在什么情况下会加载一个类?从实用角度出发,来看看验证、准备和初始化的过程核心阶段:初始化类加载器和双亲委派机制 1、前言 先来看一下JVM整体的一个运行原理。 我们首先从“.java”代码文件,编译成…

JVM类加载机制【总结】

一、JVM类加载机制: JVM类加载机制分为五个部分:加载、验证、准备、解析、初始化,下面我们分别来看一下这五个过程。 1、加载: 加载是类加载过程中的第一个阶段:这个阶段会在内存中生成一个代表这个类的java.lang.…

带你搞懂【JVM类加载机制】

文章目录 一、是什么?二、 过程1.程序2. 类加载过程3.类加载器4.类加载器初始化过程5.双亲委派机制5.1加载过程5.2为什么要有这种双亲委派机制 一、是什么? 不了解JVM加载过程,可能我们依旧能写好代码,但是了解JVM类加载过程&…

JVM类加载机制详解

目录 1.类装载子系统 1.1.类加载器ClassLoader角色 1.2.类加载执行过程 1.2.1 加载 1.2.2 链接 1.2.3 初始化 1.3.cinit 与 init 2.类加载器 2.1.类加载器的作用 2.2.类加载器的分类 3.双亲委派模型 3.1. 为什么需要双亲委派模型 3.2.如何实现双亲委派模型 4.自定…

JVM-01.JVM类加载机制

思维导图:点击查看思维导图. 类加载的过程: 加载: 在硬盘上通过IO读取字节码文件,使用类时才会进行加载。在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口 验证:…

jvm类加载机制探讨

一、类加载流程 jvm中类加载流程分为5个部分:加载loading,验证Verification,准备preparation,解析resolution,初始化initialization。 1、加载阶段,这个阶段会在内存中生成一个代表这个类的 java.lang.Cl…

浅析JVM类加载机制

浅析类加载机制 类加载器简单来说是用来加载 Java 类到 Java 虚拟机中的。Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器…

详谈JVM类加载机制

当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。 JVM执行JAVA代码的流程 通过Java命令执行代码的大体流程如下: 类加载过程 在上图中,其中loadClass的类加载过程有如下几步: 加载 &…

JVM的类加载机制《简要概述》

一、什么是类加载 类加载机制就是Java虚拟机把字节码文件中的描述类数据加载到内存中,然后对数据进行校验,转换解析,最后形成可以被虚拟机直接使用的Java类的过程。 说到类加载就不得不提到类的生命周期。 二、类的生命周期 类的生命周期&a…

JVM 类加载机制

一、Java 虚拟机 虚拟机可分为:系统虚拟机和程序虚拟机 系统虚拟机:系统虚拟机是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。例如:Visual Box、VMware 就属于系统虚拟机。 程序虚拟机:程序虚拟机…

JDK源码JVM类加载机制

JVM类加载机制 首先我们的java小程序demo,经过编译后变成.class文件,他是如何加载到内存的将.class文件 内存中有两大对象:1.类的字节码对象,只有一份在内存。2.类对象会有多份 文章目录 JVM类加载机制前言一、类加载运行全过程1…

java学习-jvm类加载机制

文章目录 一、JVM 类加载机制二、类加载器1.启动类加载器(Bootstrap ClassLoader)2.扩展类加载器(Extension ClassLoader)3.应用程序类加载器(Application ClassLoader) 三、双亲委派机制总结 一、JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证…

【面试】JVM类加载机制

本系列为大厂面试题系列的相关笔记,如有误,欢迎大家指正。 JVM类加载机制 类加载器 虚拟机设计团队把加载动作放到JVM外部实现,以便于引用程序决定如何获取所需的类,JVM提供了三种类加载器 启动类加载器 Bootstrap ClassLoade…

【JVM】JVM类加载机制

【JVM】JVM类加载机制 类加载子系统(类加载机制) 类加载器 类加载器(classloader)的作用 加载 .class 文件(平台无关的二进制字节码文件) classloader 有两种装载class的方式 (时机&#xff…

源码剖析JVM类加载机制

1 前言 我们平常开发中,都会部署开发的项目或者本地运行main函数之类的来启动程序,那么我们项目中的类是如何被加载到JVM的,加载的机制和实现是什么样的,本文给大家简单介绍下。 2 类加载运行全过程 当我们用java命令运行某个类…

JVM类加载机制简单介绍

本文为《深入理解Java虚拟机JVM高级特效与最佳实践(第三版)》一书的摘要总结 类加载时机 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型&#xff0…

JVM的类加载机制

一、类加载机制 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内****,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象&…

深入JVM类加载机制

从ClassLoad开始说起 ClassLoader顾名思义就是我们所常见的类加载器,其作用就是将编译后的class文件加载内存当中.在应用启动时,JVM通过ClassLoader加载相关的类到JVM当中.在具体了解ClassLoader之前我们先来了解下JVM的类加载机制. 1. 类加载机制 虚拟机将class文件加载到内…