【Java 虚拟机原理】Java 类加载过程 ( 加载 | 连接 - 验证 准备 解析 | 初始化 | 使用 | 卸载 )

简介: 【Java 虚拟机原理】Java 类加载过程 ( 加载 | 连接 - 验证 准备 解析 | 初始化 | 使用 | 卸载 )

文章目录

一、Java 类加载过程

0、字节码编译

1、加载

2、连接

3、初始化

总结





一、Java 类加载过程



0、字节码编译


编写好 Java 源码 Student.java ,


使用 javac 将上述 Java 源码编译成 Class 字节码文件 Student.class ,



1、加载


加载 : 通过 " 类加载子系统 " 将该字节码文件 , 加载到 Java 虚拟机内存中 的 方法区 , 然后开始执行 " 连接 " 操作 ,



类加载时机 : Java 程序执行时 , 并不是一开始将所有的字节码文件都加载到内存中 , 而是用到时才进行加载 ;


通过 new 关键字创建实例对象 ;

通过 Class 反射 获取类 ; 如 : Class.forName(“Xxx”) 获取类 ;

序列化 / 反序列化 ;

调用 clone 克隆对象 ;

有 main 函数的类 , 会默认自动加载 ;

调用子类 , 如果之前没有加载过父类 , 则 自动加载父类 ;


2、连接


连接操作 分为 3 33 个步骤 :


验证 : 对 字节码文件 进行校验 , 查看该字节码格式是否正确 , 如 : 是否以 0xCAFEBABE 开头 , 字段表 , 方发表 , 属性表 等格式是否正确 , 进行校验 ;

校验示例 : 假设校验如下字节码数据 , 原始数据是 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) 二、字节码文件示例 章节中的 Java 源码 , Class 字节码 , 字节码附加信息 ;

在 Student 构造方法中 , 会调用到 1: invokespecial #1 父类构造方法 , 如果父类有有参的构造方法且没有声明无参构造方法 , 子类必须实现一个相同参数的构造方法 , 否则就会报错 ;

Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
{
  public Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
}


准备 : 在该阶段 , 在 方法区 中 , 为 类中的静态变量 进行内存划分 , 并对这些静态变量进行 默认值赋值 , 一般赋值 0 , null 等默认值 ; 即使静态变量 static int a = 5 已经有了赋值 , 但是在该阶段暂时给该静态变量赋值 0 ;

解析 : 将 " 常量池 " 中的 " 符号引用 " 转为 " 直接引用 " ;

符号引用 : 下面就是 常量池中的 符号引用 , 引用是 以符号的形式表示出来 的 , 这并不是内存中的引用 ; 直接引用 是 将 #1 = Methodref #4.#17 样式的 符号引用 转为 指向内存地址 的 指针引用 ; JVM 线程栈 的 栈帧 中的 动态链接 , 就是持有的一个指向内存的指针 , 该指针指向 栈帧 对应方法 在运行时 常量池中的 内存地址 ; 该内存地址是在 方法区 中的 ;

Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#18         // Student.name:Ljava/lang/String;
   #3 = Class              #19            // Student
   #4 = Class              #20            // java/lang/Object


( 分析的数据是 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) 二、字节码文件示例 章节中的 Java 源码 , Class 字节码 , 字节码附加信息 ; )



3、初始化


初始化 : 对变量进行 指定赋值 ;


如 : 有静态变量 static int a = 5 , 在 连接 过程中的 准备 阶段 , 为该变量赋值默认值 0 ; 在 初始化 阶段 , 为其赋值 代码 中设置的真正的 指定初始值 5 ;




总结

借助下图理解类加载过程 ;


image.png

目录
相关文章
|
2月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
128 4
|
2月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
216 5
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
202 1
|
2月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
259 1
|
2月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
208 0
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
384 2
|
9月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
946 29
|
9月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
411 4
|
9月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。

推荐镜像

更多
  • DNS