java 类加载过程?

本文详细介绍了Java类加载的全过程,包括加载、链接(验证、准备、解析)、初始化和使用阶段。重点讨论了类的加载、静态变量的初始化、符号引用到直接引用的解析以及类的生命周期和卸载条件。内容涵盖了类的生命周期、内存分配以及方法调用的实现机制。
摘要由CSDN通过智能技术生成

过程一:Loading(加载)阶段

所谓加载,简而言之就是将Java类的字节码文件加载到机器内存中,并在内存中构建出Java类的原型——类模板对象。 也就是查找并加载类的二进制数据,生成Class的实例。

在加载类时,Java 虚拟机必须完成以下 3 件事情:

  • 通过类的全名,获取类的二进制数据流。

  • 解析类的二进制数据流为方法区内的数据结构(Java 类模型)

  • 创建 java.lang.Class 类的实例,表示该类型。作为方法区这个类的各种数据的访问

    二进制流的获取方式

    对于类的二进制数据流,虚拟机可以通过多种途径产生或获得。(只要所读取的字节码符合 JVM 规范即可)

  • 虚拟机可能通过文件系统读入一个 class 后缀的文件(最常见)

 过程二:Linking(链接)阶段

环节 1:链接阶段之 Verification(验证)

它的目的是保证加载的字节码是合法、合理并符合规范的。

验证的内容则涵盖了类数据信息的格式验证、语义检查、字节码验证,以及符号引用验证等

环节 2:链接阶段之 Preparation(准备)

准备阶段(Preparation),简言之,为类的静态变量分配内存,并将其初始化为默认值。

这里不包含基本数据类型的字段用staticfinal修饰的情况,因为final在编译的时候就会分配了,准备阶段会显式赋值。

// 一般情况:static final修饰的基本数据类型、字符串类型字面量会在准备阶段赋值
private static final String str = "Hello world";
// 特殊情况:static final修饰的引用类型不会在准备阶段赋值,而是在初始化阶段赋值
private static final String str = new String("Hello world");

 

  • 注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到 Java 堆中。

  • 在这个阶段并不会像初始化阶段中那样会有初始化或者代码被执行。

 环节 3:链接阶段之 Resolution(解析)

在准备阶段完成后,就进入了解析阶段。解析阶段(Resolution),简言之,将类、接口、字段和方法的符号引用转为直接引用。

image-20210430225015932

 

 

以方法为例,Java 虚拟机为每个类都准备了一张方法表,将其所有的方法都列在表中,当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法。通过解析操作,符号引用就可以转变为目标方法在类中方法表中的位置,从而使得方法被成功调用

 过程三:Initialization(初始化)阶段

 

4.1. static 与 final 的搭配问题

说明:使用 static+ final 修饰的字段的显式赋值的操作,到底是在哪个阶段进行的赋值?

  • 情况 1:在链接阶段的准备环节赋值

  • 情况 2:在初始化阶段<clinit>()中赋值

 过程四:类的 Using(使用)

过程五:类的 Unloading(卸载)

 

类的生命周期

当 Sample 类被加载、链接和初始化后,它的生命周期就开始了。当代表 Sample 类的 Class 对象不再被引用,即不可触及时,Class 对象就会结束生命周期,Sample 类在方法区内的数据也会被卸载,从而结束 Sample 类的生命周期。

一个类何时结束生命周期,取决于代表它的Class对象何时结束生命周期。

 

 

类的卸载

(1)启动类加载器加载的类型在整个运行期间是不可能被卸载的(jvm 和 jls 规范)

(2)被系统类加载器和扩展类加载器加载的类型在运行期间不太可能被卸载,因为系统类加载器实例或者扩展类的实例基本上在整个运行期间总能直接或者间接的访问的到,其达到 unreachable 的可能性极小。

(3)被开发者自定义的类加载器实例加载的类型只有在很简单的上下文环境中才能被卸载,而且一般还要借助于强制调用虚拟机的垃圾收集功能才可以做到。可以预想,稍微复杂点的应用场景中(比如:很多时候用户在开发自定义类加载器实例的时候采用缓存的策略以提高系统性能),被加载的类型在运行期间也是几乎不太可能被卸载的(至少卸载的时间是不确定的)。

综合以上三点,一个已经加载的类型被卸载的几率很小至少被卸载的时间是不确定的。同时我们可以看的出来,开发者在开发代码时候,不应该对虚拟机的类型卸载做任何假设的前提下,来实现系统中的特定功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值