当前位置: 首页 > news >正文

Android---Class 对象在执行引擎中的初始化过程

一个 class 文件被加载到内存中的步骤如下图所示:

装载

 装载是指 Java 虚拟机查找 .class 文件并生成字节流,然后根据字节流创建 java.lang.Class 对象的过程。

1. ClassLoader 通过一个类的全限定名包名+类名)来查找 .class 文件,并生成二进制字节流。其中 class 字节码文件的来源:1).class 文件;2)jar包,zip包;3)网络的字节流。

2. 把 .class 文件的各个部分分别解析(parse)为 JVM 内部特定的数据结构,并存储在方法区。JVM 会将这些 .lcass 文件的结果转换为 JVM 内部运行时数据结构。

3. 在内存中创建一个 java.lang.Class 类型的对象。程序在运行过程中所有对该类的访问都通过这个类对象,也就是这个 Class 类型的类对象是提供给外界访问该类的接口。

加载时机

隐式装载:在程序运行过程中,当碰到通过 new 等方式生成对象时,系统会隐式调用 ClassLoader 去装载对应的 class 到内存中。

显示装载:在编写源代码时,主动调用 Class.forName() 等方法也会进行 class 装载操作。

链接

链接过程分为3步:验证、准备、解析

1. 验证

目的是为了确保.class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危及虚拟机本身的安全。
● 文件格式检验:检验字节流是否符合class文件格式的规范,并且能被当前版本的虚拟机处理
● 元数据检验:对字节码描述的信息进行语义分析,以保证其描述的内容符合Java语言规范的要求
● 字节码检验:通过数据流和控制流分析,确定程序语义是合法、符合逻辑的
● 符号引用检验:可以看作是对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验

2. 准备

准备的主要目的是为类中的静态变量分配内存,并为其设置“0值”。

public static int value = 100;

准备阶段,JVM 会为 value 分配内存,并将其设置为0,而真正的值100 是在初始化阶段设置。

public static final int value = 100;

有 final 关键字修饰的变量会在准备阶段分配内存并设置值为100。

Java 中基本类型的默认“0值”如下:

● 基本类型(int, long, short, char, byte, boolean, float, double)的默认值为0;

● 引用类型默认值是 null。

3. 解析

解析的任务是把常量池中的符号引用转换为直接引用,也就是具体的内存地址。在这一阶段,JVM 会将常量池中的类、接口名、字段名、方法名等转换为具体的内存地址。

初始化

初始化这一阶段是执行类构造器<cinit>方法的过程,并真正初始化类变量。例如

public static int value = 100;

在准备阶段,JVM 会为 value 分配内存,并将其设置为0,而真正的值100 是在初始化阶段设置。

初始化的时机

JVM规范中严格规定了class初始化的时机,主要有以下几种情况会触发class的初始化:
1. 虚拟机启动时,初始化包含main方法的主类
2. 遇到new指令创建对象实例时,如果目标对象类没有被初始化则进行初始化操作
3. 当遇到访问静态方法或者静态字段的指令时,如果目标对象类没有被初始化则进行初始化操作
4. 子类的初始化过程如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
5. 使用反射API进行反射调用时,如果类没有进行过初始化则需要先触发其初始化
6. 第一次调用java.lang.invoke.MethodHandle实例时需要初始化MethodHandle指向方法所在的类

初始化类变量

在初始化阶段,只会初始化与类相关的静态赋值语句静态语句,也就是有 static 关键字修饰的信息。没有 static 修饰的语句块在实例化对象的时候才会执行。

Class 初始化和对象的创建顺序

面试题:在代码中使用 new 创建一个类的实例对象时,类中的静态代码块、非静态代码块、构造函数之间的执行顺序是怎样的?

对象的初始化顺序:静态变量/静态代码块 -->  普通代码块 --> 构造函数

1. 父类静态变量和静态代码块
2. 子类静态变量和静态代码块
3. 父类普通成员变量和普通代码块
4. 父类的构造函数
5. 子类普通成员变量和普通代码块
6. 子类的构造函数

总结
1. 装载:指查找字节流,并根据此字节流创建类的过程,装载过程成功的标志就是在方法区中成功创建了类所对应的 Class 对象。

2. 链接:指验证创建的类,并将其解析到 JVM 中使之能够被 JVM 执行。

3. 初始化:是将标记为 static 的字段进行赋值,并且执行 static 标记的代码语句。

http://www.lryc.cn/news/187034.html

相关文章:

  • Altium Designer实用系列(二)----PCB绘图小技巧
  • threejs-开发入门与调试设置
  • win11安装双系统Ubuntu的坎坷记录
  • 关于docker的xuexi
  • Python接口自动化测试实战详解,你想要的全都有
  • SparkSQL 外部数据源
  • leetcode做题笔记167. 两数之和 II - 输入有序数组
  • [ZJCTF 2019]NiZhuanSiWei - 伪协议+文件包含+反序列化
  • 如何提升和扩展 PostgreSQL — 从共享缓冲区到内存数据网格
  • Elasticsearch:使用 huggingface 模型的 NLP 文本搜索
  • 论文解析——异构多芯粒神经网络加速器
  • MyBatisPlus(十六)逻辑删除
  • 基于黏菌优化的BP神经网络(分类应用) - 附代码
  • C语言基础语法复习08-位域bit-fields
  • 3.2.OpenCV技能树--二值图像处理--图像腐蚀与膨胀
  • 基于FPGA的数字时钟系统设计
  • linux centos Python + Selenium+Chrome自动化测试环境搭建?
  • mysql面试题20:有哪些合适的分布式主键方案
  • git的基础操作
  • lua 中文字符的判断简介
  • SSM-XML整合
  • 线性代数小例子
  • ASP.NET Core 开发 Web API
  • QImage函数setAlphaChannel
  • 区块链、隐私计算、联邦学习、人工智能的关联
  • Unity可视化Shader工具ASE介绍——4、ASE的自定义模板使用
  • FastAPI学习-22.response 异常处理 HTTPException
  • 75.颜色分类
  • 浅谈分散式存储项目MEMO
  • ansible角色运行指定角色路径