【JVM】类加载机制

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【JVM】类加载机制

类加载机制

类加载指的是,Java 进程运行的时候,需要把 .class 文件从硬盘读取到内存,并进行一些列的校验解析的过程(程序要想执行,就得进入内存)

  • .class 文件==>类对象
  • 硬盘==>内存

类加载过程

类加载的过程,其实是在 Java 官方文档中给出的说明

  1. 加载:找到. class 文件,并且读文件内容
  2. 验证:校验 .class 文件的格式是否符合 JVM 规范要求
  3. 准备:给类对象分配内存(此时内存空间全是 0 的==>类的静态成员也就是全 0 的值)
  4. 解析:针对类中的字符串常量进行处理
  5. 把类对象的各个属性进行赋值填充==>触发对父类的加载,初始化静态成员,执行静态代码块

类加载大体的过程可以分为五 个步骤(也有资料上说是三个,这个情况就是把 2,3,4 合并成一个了)

1. 加载

把硬盘上的 .class 文件找到,打开文件,读取到文件内容(认为读到的是二进制的数据)

  • 找文件这里还有点幺蛾子(后面再说)

2. 验证

当前需要确保读到的文件的内容是合法的 .class 文件(字节码文件)格式

具体的验证依据,在 Java 虚拟机规范中,有明确的格式说明:

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html


这里的描述方式,类似与 C语言的结构体

  • 前面一列是属性的类型;后面一列是属性的名字
  • u4 就是 4 个字节的无符号整数
  1. magic

magic 也叫做 magic number,魔幻数字。广泛应用于二进制文件格式中,用来标识当前二进制文件的格式是哪种类型

二进制文件是一个非常广泛的话题。mp3mp4 是二进制,你图片也是二进制,你一个可执行程序也是二进制,你一个 .class 文件也是二进制。不同的二进制,在使用和解析的时候肯定是存在一些差别的

所以我们一般就会在二进制文件开头指定一个固定的“魔幻数字”,通过这个数字对这个文件类型进行区分

  1. minor/major_version
  • minor_version:次版本
  • major_version:主版本

平时说 Java 8,9,17… 平时表达的时候使用的版本,实际上 JVM 开发过程中内部还有版本(通过 minor/major_version 进行表示)

JVM 执行 .class 文件对的时候,就会验证版本是否符合要求。如果版本不兼容,就无法执行。一般来说,高版本的 JVM 可以运行低版本的 .class,反之不一定能行

3. 准备

给类对象申请内存空间

此时申请到的内存空间,里面的默认值,都是全 0 的。(这个阶段中,类对象里的静态成员变量的值也就相当于是 0)

4. 解析

主要是针对类中的字符串常量进行处理

解析阶段是 Java 虚拟机将常量池的符号引用替换为直接引用的过程,也就是初始化常量的过程

偏移量

class Test {
  private String s = "hello";
}

  • .class 文件中,会有一个部分用来存储“hello”这个字符串常量(常量池里面,上面验证的格式里面包含了)
  • 还有一个空间对应着 s 这个变量
  • 在上述代码中,我们很明显的知道,s 变量里面相当于保存了“hello”字符串常量的地址。但是在文件中,不存在“地址”这样的概念。谈到地址就是“内存”的地址,我们是文件,是硬盘(硬盘没有地址的概念)
  • 虽然没有地址,但是可以存储一个类似于地址的“偏移量”(文件开头到“hello”的距离)这样的概念,用来描述这个数据的位置

符号引用和直接引用

此处文件中填充给 s 的“hello”的偏移量,就可以认为是“符号引用”。接下来要把 .class 文件加载到内存中,就会先把“hello”这个字符串加载到内存中,此时“hello”就有地址了。

之后 s 里面的值就可以替换成当前“hello真实的地址了(直接引用

本来在文件中存储的并非是一个真实的地址,而是一个标记(偏移量);我们回到内存中后,我们就可以把这个数据的存储换成真实的地址了

5. 初始化

针对类对象完成后续的初始化

还要执行静态代码块的逻辑,还可能会触发父类的加载


相关文章
|
7月前
|
安全 Java
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解
44 0
|
7月前
|
安全 前端开发 Java
JDK源码级别彻底剖析JVM类加载机制
JDK源码级别彻底剖析JVM类加载机制
|
4月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
69 0
|
4月前
|
安全 前端开发 Java
【JVM 探秘】ClassLoader 类加载器:揭秘 Java 类加载机制背后的秘密武器!
【8月更文挑战第25天】本文全面介绍了Java虚拟机(JVM)中的类加载器,它是JVM的核心组件之一,负责将Java类加载到运行环境中。文章首先概述了类加载器的基本工作原理及其遵循的双亲委派模型,确保了核心类库的安全与稳定。接着详细阐述了启动、扩展和应用三种主要类加载器的层次结构。并通过一个自定义类加载器的例子展示了如何从特定目录加载类。此外,还介绍了类加载器的完整生命周期,包括加载、链接和初始化三个阶段。最后强调了类加载器在版本隔离、安全性和灵活性方面的重要作用。深入理解类加载器对于掌握JVM内部机制至关重要。
179 0
|
7月前
|
前端开发 Java 数据库连接
JVM(类加载机制)
JVM(类加载机制)
63 4
|
7月前
|
存储 缓存 安全
深入浅出JVM(三)之HotSpot虚拟机类加载机制
深入浅出JVM(三)之HotSpot虚拟机类加载机制
|
存储 算法 Java
Android 面试必备 - JVM 及 类加载机制
Android 面试必备 - JVM 及 类加载机制
|
7月前
|
前端开发 Java
深入理解Java虚拟机:类加载机制
【2月更文挑战第23天】本文深入探讨了Java虚拟机(JVM)的类加载机制,包括类加载器的层次结构、类加载的过程以及双亲委派模型。通过对JVM类加载机制的理解,可以帮助我们编写更高效的Java代码。
|
7月前
|
安全 Java 应用服务中间件
|
存储 安全 前端开发
JVM 类加载机制
JVM 类加载机制
46 0