JVM的类加载过程详细说明

关于JVM的类加载过程,可以分为以下3个阶段:加载、连接和初始化。下面分别介绍:

加载

类加载的过程就是将类的.class文件中的二进制码读入到内存中,将其放在方法区(JDK 1.8之前称为永久代,JDK 1.8之后将永久代移除,改为元空间)内,然后在堆区构造一个java.lang.Class对象,用来封装类在方法区内的数据结构。

类的加载阶段由类加载器完成,Java虚拟机中内置了三个类加载器:

  • 引导类加载器(Bootstrap ClassLoader):负责加载Java核心库,是用本地代码实现的,并不继承自java.lang.ClassLoader;
  • 扩展类加载器(Extension ClassLoader):负责加载JDK的扩展库;
  • 应用程序类加载器(Application ClassLoader):负责加载应用程序classpath目录下的类库,是最常用的ClassLoader。

在加载阶段,会执行以下过程:

  1. 通过类的全限定名获取二进制字节流;
  2. 将字节流所代表的静态存储结构转化为方法区的运行时数据结构;
  3. 在内存中生成一个代表该类的java.lang.Class对象,作为该类访问入口;
  4. Class对象的数据结构中包含了来自编译时的所有常量池、字段、方法等信息。

连接

类的连接分为三个阶段:验证、准备、解析。

1. 验证

验证阶段是为了确保被加载的类满足Java虚拟机的约束条件,以确保程序的正确性和安全性。其中包括以下4个部分:

  1. 文件格式验证:判断.class文件是否符合规范、格式是否正确等;
  2. 元数据验证:对字节码描述的信息进行语义分析,保证其符合Java语言规范;
  3. 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的;
  4. 符号引用验证:验证类自身以外的信息是否能够被正确地链接。

2. 准备

准备阶段是为类的静态变量分配内存并设置初始值的阶段。变量所使用的内存都将在方法区中进行分配,初始值为默认值。

3. 解析

解析阶段是将常量池中的符号引用替换成直接引用的过程。

初始化

初始化阶段是类加载过程的最后一个阶段,是执行类构造器()方法的过程。该方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的。当“()”方法执行时,标志着类的初始化过程完成。

示例1:

public class ClassLoaderDemo {
    public static void main(String[] args) {
        System.out.println("----------1---------------");
        new A();
        System.out.println("----------2---------------");
        new B();
    }
}
class A {
    public A() {
        System.out.println("A类的无参构造函数");
    }
    static {
        System.out.println("A类的静态代码块");
    }
    {
        System.out.println("A类的普通代码块");
    }
}
class B {
    static {
        System.out.println("B类的静态代码块");
    }
    public B() {
        System.out.println("B类的无参构造函数");
    }
}

输出结果:

----------1---------------
A类的静态代码块
A类的普通代码块
A类的无参构造函数
----------2---------------
B类的静态代码块
B类的无参构造函数

可以看出:在Java程序中,类的初始化阶段是在执行类的构造函数之前,先执行静态代码块和静态变量(即按照JVM根据类加载器链加载的顺序依次调用静态代码块和静态变量)。在当前示例中,先调用A类的静态代码块和普通代码块,然后再调用A类的无参构造方法,最后调用B类的静态代码块和无参构造方法。

示例2:

public class ClassLoaderDemo {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();
        Class<?> cls = classLoader.loadClass("java.lang.String");
        System.out.println(cls);
    }
}

输出结果:

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:662)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:429)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at ClassLoaderDemo.main(ClassLoaderDemo.java:6)

可以看出:在Java程序中,虽然类加载器可以将类动态地加载进来,但是Java虚拟机对Java核心库的保护措施非常严格,不允许通过自定义类加载器来加载Java核心库中的类,以保证Java虚拟机的安全性。因此,在当前示例中,由于尝试通过ClassLoader加载Java核心库中的String类,导致安全检查抛出异常。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JVM的类加载过程详细说明 - Python技术站

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

相关文章

  • 三大Win10新累积更新KB3206632/KB3205383/KB3205386补丁推送 附修复内容

    三大Win10新累积更新KB3206632/KB3205383/KB3205386补丁推送 附修复内容攻略 简介 最近,微软推出了三个重要的累积更新补丁,分别是KB3206632、KB3205383和KB3205386。这些补丁旨在修复一些Windows 10操作系统中的问题和漏洞,并提供更好的性能和稳定性。本攻略将详细介绍这三个补丁的安装过程和修复内容。 …

    other 2023年8月3日
    00
  • 小米手机如何给桌面的应用程序加密?

    针对“小米手机如何给桌面的应用程序加密”这个问题,我为您提供以下攻略: 1. 手动加密桌面应用程序 步骤如下: 长按桌面上需要加密的应用程序图标,选择“移动”,将应用移动到主屏幕下方的“更多应用”文件夹中。 进入“设置”应用,在“设置”中点击“应用锁”,并开启应用锁功能。 进入“应用锁”功能界面,在应用列表中选择您需要加密的应用,然后点击加锁按钮,即可完成加…

    other 2023年6月25日
    00
  • Python实现双向链表

    Python实现双向链表 双向链表是一种常见的线性数据结构,它允许在任意位置插入、删除、查找节点,具有很好的灵活性和效率。本篇文章将介绍Python如何实现双向链表,包括链表的节点定义、插入删除操作的实现、以及几个示例来说明如何使用双向链表。 链表节点定义 首先,我们需要定义一个双向链表的节点类。节点包含三个属性:前一个节点的指针prev、当前节点的值val…

    other 2023年6月27日
    00
  • 如何利用adb卸载手机预装软件(系统软件)

    如何利用adb卸载手机预装软件(系统软件) 以下是利用adb卸载手机预装软件的完整攻略: 步骤1:启用开发者选项和USB调试模式 在手机的设置中,找到“关于手机”或“关于设备”选项,连续点击“版本号”或“构建号”多次,直到开启开发者选项。然后返回到设置主界面,找到“开发者选项”,进入并启用“USB调试”模式。 步骤2:连接手机到电脑 使用USB数据线将手机连…

    other 2023年10月13日
    00
  • Element Popover 弹出框的使用示例

    Element Popover 弹出框的使用示例攻略 Element Popover 是一个常用的界面组件,用于在用户点击或悬停在某个元素上时显示相关的信息或操作选项。下面是 Element Popover 的使用示例攻略,包含两个具体的示例说明。 示例一:鼠标悬停显示信息 在这个示例中,我们将展示如何使用 Element Popover 在鼠标悬停时显示相…

    other 2023年7月28日
    00
  • Eclipse新建Android项目报错解决方案详细汇总

    下面我就为你详细讲解“Eclipse新建Android项目报错解决方案详细汇总”的完整攻略。 1.报错解决方案 1.1 Android项目无法运行问题 如果新建Android项目后无法正常运行,在Eclipse顶部菜单中依次选择“Window”、“Show View”、“Problems”,在问题列表中查看具体错误信息,通常会提示缺少Android SDK,…

    other 2023年6月26日
    00
  • vue开发者工具下载

    Vue开发者工具下载 Vue是一种流行的JavaScript框架,可用于构建大型的单页应用。在开发Vue应用过程中,Vue开发者工具是一个非常实用的工具,它可以帮助开发者进行调试和性能优化等工作。在本篇文章中,我们将介绍如何下载和安装Vue开发者工具。 下载Vue开发者工具 Vue开发者工具可以在官方网站上免费下载,官方网站的地址是 https://chro…

    其他 2023年3月28日
    00
  • Spring源码解析后置处理器梳理总结

    下面是关于”Spring源码解析后置处理器梳理总结”的完整攻略。 1. 前言 Spring是目前最为流行的Java开发框架之一,Spring的核心思想是IoC(控制反转)和AOP(面向切面编程)。Spring框架中有众多的接口和类,其中最为重要的便是BeanFactory,而Spring的后置处理器是利用BeanFactory的特性编写的一种扩展机制,可以在…

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