Java的JVM类加载机制是什么

发布时间:2023-04-20 11:31:14 作者:iii
来源:亿速云 阅读:125

本篇内容介绍了“Java的JVM类加载机制是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。当Java程序运行时,Java虚拟机会按需加载类,即在程序需要使用某个类时才会加载该类。

类的生命周期如下图:

Java的JVM类加载机制是什么

JVM的类加载机制包括加载连接( 验证准备解析)、初始化 3个阶段。

加载(Loading)

加载(Loading) 阶段主要是查找并加载字节码文件,这个文件可以是来自本地文件系统、网络、jar包等地方。加载后,生成一个对应的Class对象。

加载类时会做以下工作:

  1. 根据类的全限定名查找并读取类的二进制数据。类的二进制数据可以来自文件、网络、数据库等各种数据源。

  2. 将类的二进制数据转换成方法区内部的数据结构。在转换的过程中,JVM会对类的二进制数据进行解析和校验。

  3. 在方法区内存储该类的相关信息,包括类的名称、修饰符、常量池、字段描述符、方法描述符、接口描述符、方法表等。

  4. 生成一个代表该类的Class对象,并将该对象存放在JVM的堆内存中。Class对象包含了类的各种信息,可以用于创建类的实例、获取类的方法和字段等操作。

需要注意的是,在加载类的过程中,JVM会遵循一定的双亲委派机制,即先委派给父类加载器尝试加载,如果父类加载器无法加载,则由当前类加载器进行加载。这样可以保证类的加载不会重复,避免出现类似的类被多次加载的情况。有关类加载器可以查看我之前的文章。

加载阶段与连接阶段的部分动作(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的一部分,这两个阶段的开始时间仍然保持着固定的先后顺序。

连接(Linking)

连接阶段是Java虚拟机将类文件中的符号引用转换为直接引用的过程,会对字节码文件进行验证、准备、解析。

public static int staticValue = 123;

准备阶段初始化只是将静态变量初始化为默认值,比如上面这段代码,不同数据类型都有其默认值,初始化是只是将staticValue赋予默认值0,也就是staticValue = 0,只有在初始化阶段才会将staticValue赋值为123,也就是staticValue = 123。但是如果是staticValue是个常量public static final int staticValue = 123,准备阶段才会将staticValue赋值为123。

初始化(Initialization)

初始化阶段是指在类被首次主动使用时执行的阶段,虚拟机会执行类的初始化代码,包括静态变量的赋值和静态代码块的执行等操作。

初始化阶段是类加载的最后一个阶段,在该阶段,JVM会执行以下操作:

  1. 执行静态变量赋值操作:在这个阶段,JVM会对所有的静态变量进行初始化并赋值。这些静态变量的值通常在类定义中已经被明确定义了,JVM会根据定义进行相应的赋值操作。

  2. 执行静态代码块:如果类定义中包含有静态代码块,那么在该阶段JVM会执行这些静态代码块中的代码。

  3. 调用类的初始化方法:在Java程序中,可以使用static关键字来定义一个类的静态初始化方法(即static void methodName())。在该阶段,JVM会调用这个类的静态初始化方法。

类初始化的时机

类初始化时机包括以下四种情况:

初始化是线程安全的JVM保证一个类的初始化只会由一个线程去执行,其他线程需要等待该线程完成后才能访问该类。

下面用一个简单的Java代码示例,展示JVM类加载机制中初始化阶段的示例

public class MyClass {

    // 静态变量
    public static String staticStr = "Hello, world!";

    static {
        System.out.println("MyClass is initialized.");
    }

    // 构造方法
    public MyClass() {
        System.out.println("MyClass constructor is called.");
    }

    // 静态方法
    public static void staticMethod() {
        System.out.println("MyClass staticMethod is called.");
    }
}

在上述代码中,类MyClass包含一个静态变量staticStr、一个静态代码块和一个构造方法,以及一个静态方法staticMethod。当程序首次使用MyClass类时,JVM将会触发MyClass类的初始化阶段。可以通过下面的代码来测试类的初始化:

public class Test {
    public static void main(String[] args) {
        System.out.println(MyClass.staticStr); // 调用静态变量,触发类初始化
        MyClass.staticMethod(); // 调用静态方法,触发类初始化
        MyClass obj = new MyClass(); // 创建对象,触发类初始化
    }
}

在上面的代码中,首先输出了MyClass类的静态变量staticStr,此时会触发MyClass类的初始化;然后调用了静态方法staticMethod,同样会触发MyClass类的初始化;最后创建了一个MyClass对象,也会触发MyClass类的初始化。运行上述代码,可以看到以下输出:

MyClass is initialized.
Hello, world!
MyClass staticMethod is called.
MyClass constructor is called.

输出结果表明,MyClass类的初始化确实在首次使用该类时被触发,包括静态变量、静态代码块、静态方法和构造方法都被执行了。

此外,如果一个类是另一个类的子类,那么在使用子类时,父类也会被初始化。例如:

public class MyBaseClass {
    static {
        System.out.println("MyBaseClass is initialized.");
    }
}

public class MySubClass extends MyBaseClass {
    static {
        System.out.println("MySubClass is initialized.");
    }
}

public class Test {
    public static void main(String[] args) {
        MySubClass obj = new MySubClass(); // 创建子类对象,触发父类和子类初始化
    }
}

在上述代码中,当创建MySubClass类的对象时,将会触发MyBaseClass和MySubClass类的初始化。运行上述代码,可以看到以下输出:

MyBaseClass is initialized.
MySubClass is initialized.

“Java的JVM类加载机制是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

推荐阅读:
  1. java如何使用ApplicationContext注入Bean
  2. java如何设置文件属性

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java jvm

上一篇:Redis中lua脚本实现方法及应用场景是什么

下一篇:Flutter MultiFrameImageStreamCompleter是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》