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

yizhihongxing

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日

相关文章

  • python 如何对logging日志封装

    下面是Python对logging日志的封装攻略: 1. 理解 logging 模块的基本概念 logging 模块是Python内置的日志管理库,用于输出程序运行时的日志信息。为了更好的封装 logging 模块,我们需要先理解它的基本概念。 logging 模块中包含以下几个重要的类: Logger:logger是一个提供了应用程序可直接使用的接口。它负…

    other 2023年6月25日
    00
  • iOS UIButton 点击无响应的解决办法

    为了解决iOS UIButton点击无响应的问题,可以采用以下几种方法: 1. 检查是否禁用了用户交互 UIButton默认是开启用户交互的,但是有时候可能会在代码中禁用完就忘记开启用户交互了。如果用户交互被禁用了,按钮是不会产生响应的。 解决办法: 在代码中查找是否有地方将按钮的用户交互禁用了,如果发现了这样的代码,需要移除或注释掉。可以通过以下方式检查哪…

    other 2023年6月27日
    00
  • 电脑自动重启怎么解决?解决电脑自动重启关机问题方法(史上最全面最详细)

    电脑自动重启怎么解决? 在电脑开机时,如果出现自动重启、蓝屏等异常情况,很可能是出现了软件或硬件故障。这时候需要采取一些措施来解决这个问题。 方法一:检查CPU散热器 一些自动重启和死机的现象,往往是由于CPU散热器出现故障造成的。为解决这个问题,可以通过以下步骤: 使用工具打开电脑机箱,拆下CPU散热器 清洗CPU散热器,去除积尘 再次安装CPU散热器,并…

    other 2023年6月26日
    00
  • 家里宽带怎么换IP?

    家里宽带怎么换IP? 如果你想要更换家里宽带的IP地址,可以按照以下步骤进行操作: 联系网络服务提供商(ISP):首先,你需要联系你的网络服务提供商,告知他们你想要更换IP地址。他们将为你提供具体的操作步骤和要求。 确认网络连接类型:在进行IP地址更换之前,你需要确认你的网络连接类型。常见的网络连接类型包括动态IP和静态IP。动态IP是由ISP自动分配的,而…

    other 2023年7月30日
    00
  • 大势至文件共享服务器软件、服务器共享文件设置软件与同类对比

    下面是详细讲解“大势至文件共享服务器软件、服务器共享文件设置软件与同类对比”的完整攻略: 1. 什么是文件共享服务器软件? 文件共享服务器软件,是一种可以将计算机上的文件共享给其他计算机访问的软件。通过搭建文件共享服务器,用户可以在不同终端设备之间方便地共享和传递文件,提高工作效率和协同性。 2. 大势至文件共享服务器软件特点及设置步骤 2.1 特点 大势至…

    other 2023年6月27日
    00
  • 一步一步封装自己的HtmlHelper组件BootstrapHelper(二)

    我来为你详细讲解“一步一步封装自己的HtmlHelper组件BootstrapHelper(二)”的完整攻略。 标题 本攻略总共包含以下几个标题:- 引用相关类库- 封装组件方法- 示例1:使用BootstrapHelper生成表单- 示例2:使用BootstrapHelper生成面板 引用相关类库 在开始封装组件之前,我们需要引用Bootstrap相关类库…

    other 2023年6月25日
    00
  • C++中 ‘=default ’及‘ =delete ’的使用

    C++中 “=default” 及 “=delete” 的使用 在 C++11 中,我们可以使用 “=default” 和 “=delete” 来精确地控制类的默认函数成员的生成情况,从而提高代码性能和可读性。下面将对 “=default” 和 “=delete” 的使用进行详细讲解。 “=default” 在 C++11 中,对于类的默认函数成员,可以使用…

    other 2023年6月26日
    00
  • MyBatis-Plus 查询指定字段的实现

    让我来详细讲解“MyBatis-Plus 查询指定字段的实现”的完整攻略。 1. 环境准备 首先确保你已经准备好了以下环境: Java 8+ MyBatis-Plus 3.0+ 如果你还没有安装 MyBatis-Plus,可以使用 Maven 进行安装,添加以下依赖即可: <dependency> <groupId>com.baomi…

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