• 类加载机制的学习4___类加载的过程


         通过之前的学习,我们知道:类加载就是根据一个类的全限定名,将其字节码文件 加载到JVM内部,并创建java.lang.Class对象实例。其实,一个类的加载过程应包括:加载,连接(验证,准备,解析),初始化。

    加载:

       通过类加载器,根据一个类的全限定名,将该类的字节码文件加载到JVM中(存储在方法区内),再创建java.lang.Class对象实例,由于JVM规范中并没有要求Class对象实例应该是否应该存放在堆区中,在HotSpot VM中将Class对象实例存储在方法区内。该方法区中的Class对象实例,就会作为日后访问该类数据的入口。

    连接:

    连接是将JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中。连接阶段又是由:验证,准备,解析 3个阶段组成。

    1. 验证:主要任务是验证类的数据信息是否符合JVM的规范,是否是一个有效的字节码文件;
    2. 准备:主要是给类中的静态变量分配内存空间,并赋初始值;
    3. 解析:主要任务是将常量池中的所有符号引用变成直接引用;

    注意:Java虚拟机中并没有明确要求解析阶段必须得在初始化之后,因此可以先进行类的初始化阶段,在进行解析阶段。

    初始化:

    该阶段中,JVM会把程序中所有标识static关键字的语句全部执行一遍,会覆盖在连接的准备阶段所赋的初始值,在初始化阶段 JVM还会执行static块中的所有操作。

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    小总结:类的加载总共包含三个阶段:加载,连接,初始化。

    1. 加载:由类加载器根据类的全限定名,采用双亲委派机制将类的字节码文件加载进JVM中,并创建Class实例对象。
    2. 连接:该阶段主要是将,加载进JVM中的二进制字节流数据的类信息合并到JVM的运行时中来,其中包括三个阶段:

                  验证:检查类的数据信息是否满足JVM的规定,以及二进制字节码文件是否满足规定;

                  准备:给类中的static静态变量分配内存空间,并赋初始值;

                  解析:将常量池中的所有符号引用全部变成直接引用。

             3.初始化:执行类中的所有static语句,也包括static块。

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    初始化操作的时机选择:

    Java虚拟机对加载和连接的时机选择有很大的灵活性,但是对于初始化,却有着规范限制,一个类或者接口应该在第一次主动使用时完成初始化操作,具体包括:

    1. 在给一个类创建新对象时:包括new,反射,序列化。
    2.  调用一个的静态方法时;
    3. 调用Java API中的反射方法时;
    4. 初始化一个派生类时(其超类必须已经完成初始化操作)接口中并不适合 因为当调用超接口的非静态字段时 必须完成初始化操作;
    5. JVM启动包含main方法的类时;
    6. 调用一个类或者接口的静态字段时,并给这些静态字段进行赋值操作;

       

    public class Test {
        static{
            //构造方法被执行
            new Test();
        }
        static int v1;
        static int v2=0;
        public Test(){
            v1=10;
            v2=10;
            System.out.println("构造函数被执行");
            System.out.println("v1"+v1); //10
            System.out.println("v2"+v2); //10
        }
    
        public static void main(String[] args) {
            System.out.println("v1"+v1); //10
            System.out.println("v2"+v2); //0
        }
    }

    代码分析:static代码块是按顺序进行执行的,后来的值也会覆盖原来的值。

  • 相关阅读:
    使用 ASP.NET Core 创建 Web API
    C# 请求接口返回中文乱码→???
    无法从命令行或调试器启动服务,必须首先安装Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务器管理工具或NET START命令启动它
    制作和引用自定义图标库
    asp.net core 3.1 解决跨域的问题
    看自己以前写的代码
    图解SQL Server 数据库定时自动备份
    码云修改登录密码后终端连不上的问题
    C#中string.format用法详解
    C#高级编程之泛型详解
  • 原文地址:https://www.cnblogs.com/xbfchder/p/11428791.html
Copyright © 2020-2023  润新知