Java类加载初始化的过程及顺序

yizhihongxing

下面我将详细讲解Java类加载初始化的过程及顺序。

Java类加载初始化的过程

Java的类加载过程一般分为三个部分:类加载、链接和初始化。其中类的加载是指将类的.class文件读入内存,并将其转化成方法区中的运行时数据结构;链接是将类的常量池中的符号引用转化成直接引用的过程,然后进行内存地址的检验,最后完成方法表的预备工作;初始化则是对类的静态变量进行初始化的操作,JVM提供了五种初始化方式。

具体来说,Java类加载初始化的过程如下:

  1. 加载:这是类加载的第一个阶段,在该阶段,类加载器会从本地文件系统或者网络中查找类的字节码文件,并将其读入到JVM中的内存中。当然,在加载的过程中可能会出现各种各样的问题,如类找不到、类格式不正确、访问权限等。
  2. 链接:
  3. 校验:在这个阶段,JVM会对类进行校验,来确保它的字节码是合法的、符合Java虚拟机规范的。该阶段主要是检查字节码文件是否符合规范的内容。如果字节码文件存在错误,那么会抛出java.lang.VerifyError错误。
  4. 准备:在该阶段,JVM会为类信息在内存中分配空间,并且设置类变量的默认值(0、false、null等)。
  5. 解析:在此阶段,JVM会将符号引用替换为直接应用,也就是将常量池中的Class符号转为对应的直接引用。这个阶段可能会归并(合并)一些类或者接口,也可能导致一些类或接口没能被加载,从而抛出java.lang.NoClassDefFoundErrorjava.lang.ClassNotFoundException

  6. 初始化:这是类加载的最后一个阶段,在此阶段JVM必须保证所有静态变量在进行首次访问之前都已经被正确地初始化。JVM定义了五种初始化方式,包含:静态变量赋值、静态代码块赋值、延迟加载、粒度控制、progressive。

类初始化过程中,并不是所有的类都会被初始化。只有在以下情况下类才会被初始化:

  • 创建类的实例
  • 调用类的静态方法
  • 访问类的静态变量
  • 使用反射方式强制创建某个类或接口对应的Class对象,且该类或接口还没有被初始化
  • 初始化某个类或接口的子类。

接下来,我举两个例子来说明Java类加载初始化的过程和顺序。

示例一

我们来看一个简单的Java类SimpleClass,其代码如下:

public class SimpleClass {
    static {
        System.out.println("Static initialization block");
    }

    public static void main(String[] args) {
        System.out.println("Main method");
    }
}

在执行SimpleClass.main方法之前,这个类会被加载、链接和初始化,我们来逐步分析运行结果:

  1. 加载:在运行Java程序时,JVM会查找符号引用,当发现需要加载类时,会调用类加载器来进行加载。在该例中,类的加载通过系统类加载器(AppClassLoader)完成。
  2. 链接
  3. 校验:在该阶段,JVM会校验字节码文件,是否符合规范、正确性等。该阶段的输出为: Static initialization block
  4. 准备:在该阶段,会为类变量在内存中分配空间,并设置默认值。在该例中,在符号表中发现了类的静态变量,被初始化为0或null。
  5. 解析:在该阶段,JVM会将符号引用转换为直接引用。这里并没有符号引用需要转换,所以跳过这个步骤。

  6. 初始化:在该阶段,执行类的静态初始化。在SimpleClass中,静态代码块将被执行,并打印Static initialization block

这样上述SimpleClass类的类加载初始化过程便完整地走完了。

示例二

下面我们再来看一下更复杂一些的类的初始化顺序。下面先给出Parent父类和Child子类的定义:

class Parent {
    public static int A = 1;

    static {
        A = 2;
    }
}

class Child extends Parent {
    public static int B = A;

    public static void main(String[] args) {
        System.out.println(B);
    }
}

那么我们再分析Child类的初始化过程:

  1. 加载:Child类的加载器是系统类加载器(AppClassLoader),因为该类是通过main方法启动的。
  2. 链接:
  3. 校验:此阶段完成后执行Parent类的初始化。Parent的初始化之后的特征是子类可以使用父类的静态属性,在这个例子中执行后A的值修改为2。
  4. 准备:在该阶段,会为类变量在内存中分配空间,并设置默认值。准备阶段结束后,静态变量的值符合程序员的设定,即A=2B=0
  5. 解析:在该阶段,JVM会将符号引用转为直接引用。在这个例子中,没有需要转化的引用需要解析。

  6. 初始化。

  7. 类初始化时会初始化类中的父类
  8. 父类的静态代码块(static block)先于子类执行(源码中Parent的静态部分先于Child),且只会执行一次。
  9. 接着执行子类中的静态代码块(此处没有子类实现)
  10. 最后执行子类自身的main方法
  11. 整个过程中只执行了一次输出,最终的输出结果为:2

所以,通过上面这两个例子,我们可以看出Java类加载初始化的过程及顺序,即先加载,再链接,最后初始化。在初始化期间,首先执行父类初始化,接着执行子类的静态初始化块和静态变量初始化,最后执行子类的主方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java类加载初始化的过程及顺序 - Python技术站

(0)
上一篇 2023年6月20日
下一篇 2023年6月20日

相关文章

  • GUI程序原理分析

    GUI程序原理分析 Graphical User Interface,简称GUI,是指一种用户与计算机进行交互的方式,通常是采用图形化操作界面,用户通过鼠标点击、拖拽等方式与计算机进行交互。在现代计算机应用程序中,GUI已经成为了主流。 GUI程序的基本原理 GUI程序的基本原理是使用图形绘制库来进行图形化界面的绘制,通过用户的行为反馈(如鼠标点击、键盘输入…

    其他 2023年3月28日
    00
  • Word2016怎么保存界面布局?

    Word2016保存界面布局攻略 在Word2016中,你可以保存自定义的界面布局,以便在以后的使用中快速恢复。下面是详细的攻略,包含两个示例说明。 步骤一:自定义界面布局 打开Word2016应用程序。 在顶部菜单栏中,点击\”视图\”选项卡。 在\”视图\”选项卡中,点击\”自定义视图\”组中的\”保存当前视图\”按钮。 在弹出的对话框中,输入一个名称来…

    other 2023年9月5日
    00
  • sqlserver将数据库的数据导成excel文档方法

    概述 在SQL Server中,可以将数据库的数据导出为Excel文档,以便于数据的备份和共享。本文将为您提供一份完整攻略,介绍如何将SQL Server数据库的数据导出为Excel文档。 导出SQL Server数据库数据为Excel文档 步骤1:连接SQL Server数据库 使用SQL Server Management Studio连接SQL Ser…

    other 2023年5月5日
    00
  • win10无法连接网络怎么办?Win10提示无法连接此网络的原因与解决方案

    Win10无法连接网络怎么办? 确定网络连接问题类型 首先,我们需要确定无法连接网络的问题类型,比如是无法连接无线网络还是有线网络。如果是无线网络,则需要确定是连接不上某一个网络还是所有无线网络都无法连接。 检查网络硬件设备 如果问题出现在无线网络中,我们可以先检查一下无线路由器或者热点的硬件是否工作正常。可以尝试用其它设备测试该网络是否正常,这样就可以确认…

    other 2023年6月26日
    00
  • C++中list的使用方法及常用list操作总结

    C++中list的使用方法及常用list操作总结 在C++中,list是一个非常常用的STL容器,它能够动态地存储数据,并且对数据的访问、插入、删除等操作都非常高效。本篇文章将介绍C++中list的使用方法及常用list操作的总结。 1. list的定义 在使用list之前,需要包含头文件<list>。list的定义方式如下: #include …

    other 2023年6月27日
    00
  • mysql数据库存储过程异常处理

    MySQL数据库存储过程异常处理 MySQL存储过程是一种用户定义的可重用的代码块,可以完成一些特定的操作。在存储过程中,处理异常也是非常重要的一部分。处理异常可以保证程序的稳定性,避免系统崩溃等情况的发生。 在MySQL数据库中,使用 DECLARE 语句声明异常变量,使用 SIGNAL 语句来抛出异常。 异常处理流程 MySQL数据库存储过程中的异常处理…

    其他 2023年3月29日
    00
  • Windows 7 64位系统手动添加Editplus到鼠标右键的方法

    下面是 Windows 7 64 位系统手动添加 Editplus 到鼠标右键的方法。 方法一:修改注册表 按下 Win + R 组合键打开运行窗口,输入 regedit,回车以打开注册表编辑器。 导航至 HKEY_CLASSES_ROOT\*\shell,右键选择新建 > 键,命名为 EditwithEditplus。 在 EditwithEditp…

    other 2023年6月27日
    00
  • webpack 4 简单介绍

    webpack 4 简单介绍 Webpack 是一个 JavaScript 模块打包工具。它可以将多个 JavaScript 模块打包成一个文件,并且可以处理 CSS、图片等其他类型的文件。Webpack 在前端开发领域获得了广泛的应用,是构建现代 Web 应用的重要工具。 最近,Webpack 4 正式发布,新版本带来了很多新特性和改进。本文将简单介绍 W…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部