Java虚拟机JVM类加载机制(从类文件到虚拟机)

Java虚拟机JVM类加载机制是Java程序运行的重要组成部分。在执行Java程序之前,虚拟机需要将程序所需的类加载到内存中,然后才能对程序进行解释执行。在这个过程中,虚拟机采用了特定的类加载机制,这种机制能够确保程序在运行时能够正常地使用所需的类库和资源。

Java虚拟机JVM类加载机制的完整攻略可以分为以下几个步骤:

1. 加载

当虚拟机需要加载类时,会首先到指定的类路径中查找该类的字节码文件。如果找到了该文件,则虚拟机会使用特定的类加载器对该类进行加载,并将其保存到内存中。如果没找到该文件,则会抛出ClassNotFoundException异常。

Java虚拟机JVM类加载机制中常用的一种类加载器是URLClassLoader。它能够从指定的URL路径中加载类文件。例如,我们可以通过以下代码创建一个URLClassLoader对象,并使用它加载指定的类文件:

URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:///path/to/classfile")});
Class<?> cls = classLoader.loadClass("com.example.MyClass");

2. 验证

在加载完类文件后,虚拟机会对其进行验证。这一过程会检查字节码文件的格式是否正确,并且会检查该类是否符合Java虚拟机的规范。例如,虚拟机会检查该类是否有超过65535个常量等。

如果该类未通过验证,则虚拟机会抛出VerifyError异常。这种异常通常意味着该类文件已经被篡改过,或者该类是由不受信任的代码生成的。

3. 准备

在验证通过后,虚拟机会为该类分配内存空间,并给类中的每个静态变量赋初值。这些初值通常都是默认值,例如:整型的为0,对象引用的为null等。

4. 解析

在准备过程中,虚拟机会为每个类中的符号引用(例如方法调用和字段访问)分配一个确定的内存地址。这个过程被称为解析。解析主要分为两个阶段:类解析和方法解析。

类解析是将每个类的符号引用转换为一个确定的内存地址,该地址指向该类在内存中的实际地址。这一过程需要检查该类是否已经被加载到内存中。如果没有,虚拟机会继续加载该类,并分配内存空间。如果已经加载,则直接将该类的内存地址返回。

方法解析是将每个方法的符号引用转换为一个指向该方法实际代码所在位置的内存地址。这一过程通常在方法调用之前进行。解析过程会查找该方法所在类的内存地址,并根据方法名和参数类型在该类中查找对应的方法实现。

5. 初始化

在解析完类中的所有符号引用后,虚拟机会执行该类的初始化方法。该方法通常是一个静态方法,用于执行一些初始化操作,例如为静态变量赋值和执行静态代码块等。如果该类没有定义初始化方法,则不进行该步骤。

示例一:

class MyClass {
  public static void main(String[] args) {
    System.out.println("Hello, world!");
  }
}

以上为一个典型的Java程序,使用JVM时会先进行类加载,接下来我们就从class文件开始,具体说明一下JVM类加载机制的过程。

加载

JVM会在类路径下寻找 MyClass.class 文件,找到以后会把它读入内存,并产生一个对应的 Class 对象。如果找不到会抛出 ClassNotFoundException 错误。

验证

在类加载时,JVM会校验 MyClass.class 文件的字节码的正确性。如果校验不通过,会抛出 VerifyError 错误。

准备

如果 MyClass 类中有静态成员变量或者静态代码块,JVM 会为它们在内存中分配空间并设置默认的初始值(int 类型为 0,对象类型为 null)。

解析

JVM 会把 MyClass 类中所有符号引用全部加以解析,如在该类中使用了其他类,JVM 会递归调用这些类的加载(加载、验证、准备、解析,最后初始化),直接完全解析完成后,所有的符号引用都会映射到一个具体的内存地址,从而准确地指向对应的代码。

初始化

在解析完所有符号引用之后,JVM 会执行 MyClass 类的初始化方法。在本例中,只有 main 方法是静态的,所以它会被执行。

示例二:

class MyGreeting {
  static String greeting = "Hello";

  static {
    greeting = greeting + ", world!";
  }
}

class MyClass {
  public static void main(String[] args) {
    System.out.println(MyGreeting.greeting);
  }
}

以上为一个稍复杂的 Java 程序,MyGreeting 类有一个静态属性 greeting,和一个静态代码块,会对这个属性赋值。在 main 方法中,我们打印出 MyGreeting.greeting 的值,看看会输出什么。

加载

JVM 会在类路径下每个类的包名对应的文件夹中寻找每个类的 class 文件,这时 MyGreeting 类会被先加载,然后 MyClass 类会被加载。

验证

和之前一样,对 MyClass.class 和 MyGreeting.class 文件的字节码进行校验,保证其正确性。

准备

因为 MyGreeting 类中有静态成员变量 greeting,JVM 会分配这个变量空间,并将它默认值(null),然后开始初始化这个类。注意,初始化只会执行一次,即使初始化代码被定义在多个静态代码块中。

解析

MyGreeting 类中的静态代码块会被执行,更新 greeting 的值为 "Hello, world!"。

初始化

MyGreeting 类初始化完成,MyClass 开始执行 main 方法。main 中虽然没有任何定义,但是打印语句中使用到了 MyGreeting 类,JVM 会保证静态代码块被执行,并将正确的值输出(Hello, world!)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java虚拟机JVM类加载机制(从类文件到虚拟机) - Python技术站

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

相关文章

  • jdbc的驱动包下载

    当然,我可以为您提供“JDBC的驱动包下载”的完整攻略,过程中包含两条示例说明。攻略如下: JDBC的驱动包下载 JDBC是Java数据库连接的标准API,它允许Java用程序与各种关系型数据库进行交互。在使用JDBC之前,您需要下载适当的JDBC驱动程序。在本教程中我们将介绍如何下载JDBC驱动程序。 步骤1:确定您的数据库类型 首先,您需要确定您要连接的…

    other 2023年5月9日
    00
  • mysql启动服务时提示’服务名无效’

    mysql启动服务时提示”服务名无效” 如果你在Windows上安装了MySQL数据库,并试图使用服务管理器启动MySQL服务时,可能会遇到一个常见的错误: “服务名无效”。这种情况通常发生在你尝试重新安装或更新MySQL时。 原因 这个问题通常是由于MySQL服务的重命名或删除导致的。如果以前已经安装了MySQL,然后你重新安装MySQL时更改了服务名称,…

    其他 2023年3月29日
    00
  • VsCode配置java环境的详细图文教程

    下面是VsCode配置Java环境的详细图文教程。 步骤一:安装JDK 首先需要下载和安装JDK,可以从Oracle官网上下载对应版本的JDK,下载地址: https://www.oracle.com/java/technologies/javase-downloads.html 根据操作系统选择合适的版本进行下载,安装时一路“下一步”即可。 步骤二:配置环…

    other 2023年6月27日
    00
  • Spring WebFlux 响应式编程学习笔记(一)

    Spring WebFlux 响应式编程学习笔记(一) 什么是Spring WebFlux Spring WebFlux 是 Spring Framework 5 中新加入的一个模块,用于支持响应式编程。响应式编程可以帮助我们更加高效地处理异步、非阻塞的IO操作,并能够应对高并发场景。 与传统的 SpringMVC 不同,Spring WebFlux 中的控…

    其他 2023年3月28日
    00
  • Java使用嵌套循环模拟ATM机取款业务操作示例

    Java使用嵌套循环模拟ATM机取款业务操作示例攻略 本攻略将详细讲解如何使用Java编写一个模拟ATM机取款业务操作的示例程序。在这个示例中,我们将使用嵌套循环来模拟ATM机的交互过程。 步骤一:创建一个ATM类 首先,我们需要创建一个名为ATM的Java类,用于模拟ATM机的行为。在这个类中,我们将定义ATM机的初始余额和一些方法来处理取款操作。 pub…

    other 2023年7月28日
    00
  • 整理java读书笔记十五之java中的内部类

    下面是整理 Java 读书笔记十五之 Java 中的内部类的完整攻略。 什么是Java中的内部类 Java中的内部类就是在一个类的内部定义另一个类。内部类可以看作是外部类的一个成员,和其他成员一样,可以被类访问控制修饰符所控制。与外部类不同的是,内部类可以直接访问外部类的成员,包括私有成员,这个特征非常有用。 Java中的内部类有如下几种形式: 形式 描述 …

    other 2023年6月27日
    00
  • 鸿蒙系统开发者模式如何进入?鸿蒙系统进入开发者模式的方法

    进入鸿蒙系统的开发者模式,需要经过以下步骤: 打开鸿蒙系统的设置应用:在主屏幕或应用列表中找到“设置”应用,点击进入。 找到“系统”选项:在设置应用中,向下滑动屏幕直到找到“系统”选项,点击进入。 进入“关于手机”页面:在“系统”页面中,向下滑动到最底部,点击“关于手机”进入详细信息页面。 找到“版本号”选项:在“关于手机”页面中,找到“版本号”选项,连续点…

    other 2023年6月26日
    00
  • 让sagemaker在aws上带你入门机器学习

    让SageMaker在AWS上带你入门机器学习 Amazon SageMaker是一种全托管的机器学习服务,可帮助开发人员和数据科学家轻松构建、训练和部署机器学习模型。本文将介绍如何使用SageMaker在AWS上入门机器学习。 步骤一:创建SageMaker实例 在使用SageMaker之前,需要创建一个SageMaker实例。以下是创建SageMaker…

    other 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部