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日

相关文章

  • Android手把手教大家制作APP首页(下拉刷新、自动加载)

    Android手把手教大家制作APP首页(下拉刷新、自动加载)完整攻略 1. 引入依赖库 在build.gradle文件中添加以下依赖: implementation ‘com.github.yalantis:PullToRefresh:1.2.0’ 2. 创建布局文件 在activity_main.xml文件中添加PullToRefreshView和Rec…

    other 2023年6月25日
    00
  • SignalR Self Host+MVC等多端消息推送服务(二)

    首先需要明确一下本文的主题是 SignalR Self Host+MVC 等多端消息推送服务,该主题主要包含以下内容: SignalR 框架的基本概念和实现原理 SignalR Self Host 实现消息推送 在 MVC 项目中集成 SignalR 前端页面中接收消息和发送消息 在这篇文章中,我将详细讲解以上四个部分内容,其中包含了一些相关的示例,方便大家…

    other 2023年6月27日
    00
  • 使用 Django 进行测试驱动开发

    使用 Django 进行测试驱动开发攻略 测试驱动开发(Test-Driven Development,TDD)是一种软件开发方法论,其中测试在开发过程中起到了至关重要的作用。在使用 Django 进行测试驱动开发时,我们可以按照以下步骤进行: 步骤一:编写测试用例 首先,我们需要编写测试用例来定义我们希望代码实现的功能。在 Django 中,我们可以使用内…

    other 2023年7月27日
    00
  • C语言中的四种常量详解

    C语言中的四种常量详解 在C语言中,常量是指在程序中固定不变的值,我们可以通过常量来给程序提供基本的数据。C语言中共有四种类型的常量,包括整型常量、浮点型常量、字符常量和字符串常量。在本文中,我们将为大家详细讲解这四种类型的常量。 整型常量 整型常量是指仅包含数字的常量。它可以是十进制、八进制、或十六进制。整型常量默认为十进制。下面是一些整型常量的示例: i…

    other 2023年6月27日
    00
  • 超星尔雅12倍速播放脚本

    当然,我很乐意为您提供“超星尔雅12倍速播放脚本”的完整攻略。以下是详细的步骤和示例说明: 安装脚本 要安装“超星尔雅12倍速播放脚本”,需要先安装Tampermonkey插件。Tampermonkey是一款浏览器插件,可以用于管理用户脚本。以下是安装Tampermonkey的步: 打开浏览器,访问Tampermonkey官网(https://www.tam…

    other 2023年5月8日
    00
  • 本文讲述下windows下使用rsync备份数据

    Windows下使用rsync备份数据的完整攻略 本文将为您提供Windows下使用rsync备份数据的完整攻略,包括介绍、使用方法和两个示例说明。 介绍 rsync是一种常用的数据备份工具,可以在不同的系统之间同步文件和目录。在Windows系统中,可以使用Cygwin或MinGW等工具来安装rsync,并使用rsync进行数据备份。本文将介绍Window…

    other 2023年5月6日
    00
  • 魔兽世界怀旧服狂暴战输出循环怎么样 狂暴战PVE手法分享

    魔兽世界怀旧服狂暴战输出循环怎么样 – 狂暴战PVE手法分享 狂暴战PVE输出循环 狂暴战的PVE输出循环可以分为两个阶段:暴饮暴食和食指扫射。下面我们来详细讲解这两个阶段的循环: 暴饮暴食阶段 在暴饮暴食阶段,你需要先进行冲锋,然后使用图腾破,接着使用斩杀,这样能够让你尽快进入狂怒模式。在狂怒模式下,你需要保持暴击率尽可能高,所以在能够的情况下优先选择暴击…

    other 2023年6月27日
    00
  • Typescript井字棋的项目实现

    Typescript井字棋项目实现攻略 项目概述 本项目旨在使用Typescript编写一个井字棋游戏的网页应用。通过本项目的实现,你将学会如何使用Typescript创建对象、定义接口、编写类方法以及进行页面交互。 准备工作 在开始实现项目之前,你需要完成以下准备工作:1. 安装Node.js和npm(如果尚未安装)。2. 确保你已经掌握了基本的HTML、…

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