Java类加载过程

Java类加载一共经历7个过程

JVM将类描述数据从.class文件中加载到内存,并对数据进行,解析和初始化,最终形成被JVM直接使用的Java类型。 类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。 ——《深入理解Java虚拟机 JVM高级特性与最佳实践》

在这里插入图片描述

1. 加载(Loading)

简单来说,类加载阶段就是由类加载器负责根据一个类的全限定名(全限定名:包名+类名)来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转为一个与目标类型对应的java.lang.Class对象实例(Java虚拟机规范并没有明确要求一定要存储在堆区中,只是hotspot选择将Class对应哪个存储在方法区中),这个Class对象在日后就会作为方法区中该类的各种数据的访问入口。加载阶段由类加载器负责,过程见类加载器;

2. 链接(Linking)

链接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中,经由验证、准备和解析三个阶段。
(1)验证(Verification):验证类数据信息是否符合JVM规范,是否是一个有效的字节码文件,验证内容涵盖了类数据信息的格式验证、语义分析、验证操作等。
  • 格式验证
    验证是否符合class文件规范

  • 语义验证
    检查一个被标记为final的类型是否包含子类;检查以一个类中的final方法是否被子类进行重写;确保父类和子类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)

  • 操作验证
    在操作数栈中的数据必须进行正确的操作,对常量池中的各种符号引用执行验证(通常在解析阶段执行,检查是否通过引用中描述的全限定名定位到指定类型上,以及类成员信息的访问修饰符是否允许访问等)


(2)准备(Preparation):准备阶段负责为类中static变量分配空间,并初始化(与程序无关,系统初始化);被final修饰的静态变量,会直接赋予原值;类的字段属性表中存在ConstantValue(常量)属性,则在准备阶段,其值就是ConstantValue(常量)的值。
(3)解析(Resolution):解析阶段负责将常量池中所有符号引用转换为直接引用(得到类或者字段、方法在内存的指针或者偏移量,以便直接调用该方法),这个可以在初始化之后再执行。可以认为是一些静态绑定的会被解析,动态绑定则只会在运行时进行解析;静态绑定包括一些final方法(不可以重写),static方法(只会属于当前类),构造器(不会被重写);

3.初始化(Initiazation)

初始化阶段是类加载过程的最后阶段,初始化阶段负责将所有static域按照此程序指定操作对应执行(赋值static变量,执行static块)。如果执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的所有操作。所有类变量初始化语句和静态代码块都会在编译时被前端编译器放在收集器里头,存放到一个特殊的方法中,这个方法就是类/接口初始化方法。该方法的作用就是初始化一个变量,使用户指定的值覆盖之前在准备阶段设定的初始值。任何invoke之类的字节码都无法调用方法,因为该方法只能在类加载的过程中由JVM调用。
如果父类话没有被初始化,那么优先对父类初始化,但在方法内部不会显示调用父类的方法,由JVM负责保证一个类的方法执行前,它的父类方法已经被执行。
JVM必须确保一个类在初始化的过程中,如果是多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程。
上述阶段通常都是允许交叉混合,没有严格的先后执行顺序;

4.使用

5.卸载


类加载器

类加载器的主要任务:是类加载过程中的加载操作:根据一个类的全限定名读取该类的二进制字节流开发者可以通过编写自定义类加载器来自定义类的加载规则。

类加载器分类

  • 启动类加载器/Bootstrap ClassLoader

    在HotSpot虚拟机中,Bootstrap ClassLoader用C++语言编写并嵌入JVM内部,主要负责加载JAVA_HOME/lib目录中的所有类,或者加载由选项-Xbootcalsspath指定路径下的类;
  • 拓展类加载器/AppClassLoader

    ExClassLoader继承ClassLoader类,负责加载用户类路径ClassPath下的所有类型,一般情况下为程序的默认类加载器;
  • 自定义类加载器

    Java虚拟机规范将所有继承抽象类java.lang.ClassLoader的类加载器,定义为自定义类加载器;
  • 双亲委派模型

    在这里插入图片描述

    双亲委派过程

    当一个类加载器收到类加载任务时,立即将任务委派给它的父类加载器去执行,直至委派给最顶层的启动类加载器为止。如果父类加载器无法加载委派给它的类时,将类加载任务退回给它的下一级加载器去执行;
    除了启动类加载器以外,每个类加载器拥有一个父类加载器,用户的自定义类加载器的父类加载器是AppClassLoader;
    双亲委派模型可以保证全限定名指定的类,只被加载一次;
    双亲委派模型不具有强制性约束,是Java设计者推荐的类加载器实现方式;
    这个博客写的很不错: 博客
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值