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知识库 -> 深入理解Java虚拟机——类加载过程 -> 正文阅读

[Java知识库]深入理解Java虚拟机——类加载过程

一、加载阶段

1.1、加载的概述

  • “加载”是“类加载”(Class Loading)过程的一个阶段,在加载阶段,虚拟机需要完成以下3件事情:
    (1)、通过一各类的全限定名来获取定义此类的二进制字节流;
    (2)、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    (3)、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

1.2、加载的加载源

  • 从ZIP包中读取。
  • 从网络中获取。 最典型的应用就是Applet。
  • 运行时计算生成。 这种场景使用最多的就是动态代理技术,在java.lang.reflect.Proxy中,就是用了ProxyGenerator.generateProxyClass来为特定接口生成形式为“$Proxy”的代理类的二进制字节流。
  • 由其他文件生成。 最典型的应用就是JSP。
  • 从数据库中读取。

二、验证阶段

2.1、验证的目的

  • 为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

2.2、验证阶段完成的4个阶段检验动作

2.2.1、文件格式验证

  • 第一阶段要验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。这一阶段可能包含下面这些验证点。
    (1)、是否以魔数0xCAFEEBABE开头;
    (2)、主、次版本号是否在当前虚拟机处理范围之内;
    (3)、常量池的常量中是否有不被支持的常量类型;
    (4)、指向常量的各种索引中是否有指向不存在的常量或不符合类型的常量;
    (5)、Class文件中各个部分及文件本身是否有被删除的或附加的其他信息等等。

2.2.2、元数据验证

  • 第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求。这个阶段可能包含下面这些验证点。
    (1)、这个类是否有父类(除了java.lang.Object之外,所有的类都应当有父类);
    (2)、这个类的父类是否继承了不允许被继承的类(被final修饰的类);
    (3)、如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法;
    (4)、类中的字段、方法、是否与父类产生矛盾(例如覆盖了父类的final字段,或者出现不符合规则的方法重载,例如方法参数都一致,但返回值类型却不同等等)。

2.2.3、字节码验证

  • 第三阶段的是整个验证过程中最复杂的一个阶段,主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。这个阶段可能包含下面这些验证点。
    (1)、保证任意时刻操作数栈的数据类型与指令码序列都能配合工作;
    (2)、保证跳转指令不会跳转到方法体以外的字节码指令上;
    (3)、保证方法体中的类型转换是有效的等等。

2.2.4、符号引用验证

  • 最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三阶段——解析阶段中发生。通常需要校验下列内容:
    (1)、符号引用中通过字符串描述的全限定名是否能找到对应的类;
    (2)、在指定类中是否存在符合方法的字段描述以及简单名称所描述的方法和字段;
    (3)、符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问等等。

三、准备阶段

3.1、准备阶段的概述

  • 准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。

  • 这时候进行内存分配的仅包含类变量(被static修饰的变量),而不包含实例变量,实例变量将会在对象实例化时随着对象一起分配Java堆中。

  • 这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:
    public static int value = 123; 那么变量value在准备阶段过后的初始值为0而不是123。

  • 假设一个类变量的定义为: public static final int value = 123; 编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就回根据ConstantValue的设置将fvalue赋值为123。

四、解析阶段

4.1、解析阶段的概述

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

4.2、符号引用、直接引用的概述

  • 符号引用
    符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量。
  • 直接引用
    直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。

4.3、解析动作

  • 类或接口的解析;
  • 字段解析;
  • 类方法解析;
  • 接口方法解析;

五、初始化阶段

5.1、初始化阶段的概述

  • 类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的Java程序代码。

5.2、< clinit> 方法

  • 初始化阶段是执行类构造器< clinit> ()方法的过程。
  • < clinit> ()方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的。
  • < clinit> ()方法与类的构函数(或者说实例构造器< init>()方法)不同,它不需要显式地调用父类构造器,虚拟机会保证在子类的 < clinit> ()方法执行之前,父类的 < clinit> ()方法已经执行完毕。
  • 由于父类的 < clinit> ()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作。
  • < clinit> ()方法对于类或者接口来说并不是必需的,如果一个类中没有静态语句块,也没有对变量的赋值操作,name编译器可以不为这个类生成 < clinit> ()方法。
  • 接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因为接口与类一样都会生成 < clinit> ()方法。
  • 虚拟机会保证一个类的 < clinit> ()方法在多线程的环境中被正确的加锁、同步。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 20:35:37  更:2022-03-21 20:37:19 
 
开发: 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 9:44:21-

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