IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【JVM】类加载过程精炼总结 -> 正文阅读

[Java知识库]【JVM】类加载过程精炼总结

类加载过程

Class文件需要加载到虚拟机中才能运行,虚拟机加载Class类型文件主要的步骤如下:
在这里插入图片描述

  • 加载、验证、准备、初始化这4个过程过程是按照这种顺序按部就班地开始的,而解析阶段不一定;
  • 按顺序开始,而不是进行,因为这些阶段通常是相互交叉地混合进行的;

问题:什么时候必须立即对类进行“初始化”

加载、验证、准备自然需要在此之前开始;

  • 遇到new、getstatic、putstatic或invokestatic这四条字节码指令时,代码场景:

能够生成这四条指令的典型Java代码场景:

  1. 使用new关键字实例化对象时;
  2. 读取/设置一个类型的静态字段时
  3. 调用一个类型的静态方法时
  • 使用java.lang.reflect包的方法对类型进行反射调用的时候;
  • 当初始化的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化
  • 当虚拟机启动的时候,用户需要执行一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个类;
  • 当一个接口被default关键字修饰了接口的方法,如果有这个接口的实现类发生了初始化,那么该接口要在之前被初始化;

这几种场景中的行为,被称为对一个类型进行主动引用
出此之外,所有引用类型方式都不会被触发初始化,被称为被动引用;

被动引用案例:

  1. 通过子类引用父类的静态字段(对于静态字段,只有直接定义这个字段的类才会被初始化);
  2. 通过数组定义的引用类,不触发类的初始化;
  3. 常量在编译阶段会被存入调用类的常量中,本质上没有直接引用到定义常量的类,因此不触发定义常量类的初始化。

1、加载

“加载”阶段是整个“类加载”过程中的一个阶段(别混淆)

(1)加载步骤

  1. 通过一个类的全限定名来获取定义此类的二进制字节流;
  2. 将此字节流所代表的静态存储结构转化方法区的运行时数据结构
  3. 在堆内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
    在这里插入图片描述

(2)特点

JVM规范中对加载的三个步骤点的要求不是特别具体,因此有很大的灵活度

  • 没有指明二进制字节流必须得从哪里获取、怎么获取,所以留给用户在类加载阶段很大的发挥空间(eg:从zip包中读取等)
  • 非数组类型的加载阶段是开发人员可控性最强的阶段,可用JVM中内置的引导类加载器,也可以用用户自定义的类加载器去完成(重写一个类加载器的loadClass()方法)。
  • 数组类不通过类加载器创建,它是由Java虚拟机直接在内存中动态构造出来的(但其中元素类型还是要靠类加载器来完成加载的)。

(3)加载阶段结束后的场景

  • 被加载的类的二进制字节流按照虚拟机所设定的格式存储在方法区中;
  • Java堆内存中会实例化出来一个java.lang.Class类的对象(程序访问方法区中类型数据的外部接口)
  • 加载阶段和连接阶段内容交叉进行的,加载阶段尚未结束,连接阶段可能就已经开始了。

2、连接

连接阶段中三个小阶段的总结:
在这里插入图片描述

(1)验证

1、格式验证

验证字节流是否符合虚拟机的规范

  1. 是否以0xCAFEBABE开头;
  2. 主、次版本号是否在当前虚拟机的处理范围内
  3. 常量池中的常量是否有不被支持的类型

2、元数据验证
对字节码描述的信息进行语义分析(数据类型校验),以保证其描述的信息符合Java语言规范的要求

这个阶段可能包括的验证点如下:

  1. 这个类是否有父类(除了java.lang.Object外,所有类都有父类)
  2. 这个类的父亲是否继承了不被允许被继承的类(被final修饰的类)
  3. 如果这个类不是抽象类,是否实现了其父类或接口中所要求实现的所有方法
  4. 类中的字段、方法是否与父类产生矛盾(覆盖了父类的final字段,出现不符合规范的方法重载…)

3、字节码验证
通过数据流和控制流分析,确保程序语义是合法的、符合逻辑的。比如保证任意时刻操作数栈和指令代码序列都能配合工作。

4、符号引用验证
发生时间:
此阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。
作用:确保解析行为能够正常执行
符号引用验证可以看做是对类自身以外(常量池中的各种符号引用)的各类信息进行匹配性校验。通俗来讲,该类是否缺少或被禁止访问它依赖的某些外部类、方法、字段等资源。

(2)准备

作用
为类变量(静态变量,被static修饰的变量)分配内存设置类变量初始值

注意

  1. 不包括实例变量,实例变量在对象实例化时随对象一块分配在Java堆中;
  2. 从概念上说,类变量使用的内存应该在方法区中分配(永久代时符合此逻辑)。但JDK8开始,HotSpot将原本放在永久代中的字符串常量池、静态变量等移动到了堆中,此时类变量会随着Class对象一起存放在Java堆中。
  3. 类变量的初始值“通常情况下”是数据类型默认的零值(eg:0、0L、null、false等)
    “特殊情况”类字段被final修饰了public static final int value=111 ,那么准备阶段此类变量就会被赋值为111。

(3)解析

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

在程序执行方法时,系统需要明确知道这个方法所在的位置。Java 虚拟机为每个类都准备了一张方法表来存放类中所有的方法。当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法了。
通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。

3、初始化

执行初始化方法<clinit>()方法的过程

在准备阶段,类变量已经赋过一次零值了,而在初始化阶段,则会根据程序员编写的代码去初始化类变量。

<clinit>()方法

1、如何产生?
该方法是编译器自动收集类中所有类变量的赋值动作和静态语句块中语句合并产生,编译器收集的顺序是由语句在源文件中出现的顺序决定的。

2、非法前向引用变量
static块中只能访问到定义在static块之前的变量,定义在它之后的变量,在前面的static块中可以赋值,但是不能访问

3、如何对待父类?

  • 与类的构造函数不同,<clinit>()方法不需要显式调用父类构造器(Java虚拟机保证在子类<clinit>()执行前,父类的<clinit>()已经执行完毕)。
  • 父类中定义的静态语句块要优先于子类的变量赋值操作

3、非必需
<clinit>()对类或接口来说并不是必须的,如果一个类中没有静态语句块,也就没有对变量的赋值操作,那么编译器可以不为这个类生成<clinit>()方法

4、接口的不同点

  • 不能使用静态语句块,但仍有变量初始化的赋值操作
  • 执行接口<clinit>()方法不需要先执行父类接口的<clinit>()
  • 只有当父类接口中定义的变量被使用时,父类接口才会被初始化
  • 接口的实现类在初始化时也一样不会被执行接口的<clinit>()方法

5、线程同步
Java虚拟机必须保证一个类的<clinit>()方法在多线程环境中被正确地加锁同步

如果多个线程同时去初始化一个类,那么只有其中一个线程去执行这个类的<clinit>()方法,其他线程都阻塞等待,直到活动线程执行完毕<clinit>()方法。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:18:07  更:2022-03-12 17:21:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:34:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码