JVM如何加载Java类的?

前言

我们知道Java语言的类型可以分为两大类:基本类型 「primitive types」和引用类型「reference types」.
对于Java的基本数据类型是Java虚拟机定义好的.至于另一大类 「引用数据类型」, Java将其分为四种类型:

  • 接口
  • 数组
  • 泛型参数

由于 「泛型参数」 在编译时期会被擦除, 因此Java虚拟机的类型实际上只有三种.

接口数组当中,「数组」是由Java虚拟机直接生成的, 类、接口则有对应的「字节流」.

最常见的字节流则属于由Java编译器生成的「class」文件.除此之外我们还可以在程序内部生成、直接从网络当中获取(如applet)的字节流.

这此不同形式的「字节流」都会被加载到Java虚拟机中, 成为类或者接口.
加载过程

从.class文件中的类到内存里的类, 按先后顺序需要经过加载、链接、初始化三个过程.

其中「链接过程」当中还需要进行验证.
内存中的类没有经过初始化,同样是不能能使用.

加载

「查找」是为了查找字节流,并且据此创建类的过程.对于数组来说,是没有字节流的,而是由Java虚拟机直接生成的对于其它类型来说, Java虚拟机则需要借助类加载器来完成查找字节流的的过程.

加载器

  1. bootstrapClassLoader(启动类加载器)
    • 最顶层的加载器,由c++实现
    • 负责加载%JAVA_HOME%/lib目录下的jar包和类,或者被-Xbootclasspath参数指定的路径中的所有的类.
  2. 扩展类加载器「Extension Class Loader」
    • 继承于java.lang.ClassLoader
    • 主要负责加载%JAVA_HOME%/lib/ext/下的jar包和类,或者被java.ext.dirs系 统变量所指定的路径下的jar包.
  3. 应用类加载器「Application Class Loader」
    • 继承于java.lang.ClassLoader
    • 面向用户的类加载器
    • 负责加载当前应用classpath下的jar和类.

双亲委派模型

双亲委派模型

  • 每一个类都有它对应的类加载器.
  • 系统中的ClassLoader在协同的时候会默认启用双亲委派模型.
  • 在类加载的过程中,首先会判断这个类是否被加载过.
  • 被加载过 -> 直接返回
  • 没有被加载过 -> 尝试加载

加载流程

  • 先把加载类的请求委派给该父类加载器的loadClass进行处理.
  • 因此所有的请求最终都应该传送到最顶层的类加载器BootstrapClassLoader中.
  • 当父类无法处理时,才需要自己处理.
  • 当父类加载器为null时,会使用BootstrapClassLoader作为其父类加载器
双亲委派模型的优点
  • 保证了java的稳定的运行, 可以保证类不被重复加载.
  • jvm区分不同的类不仅仅是根据全类名, 相同的类文件被不同的类加载器加载产生的也是两个不同的类.
  • 保证java核心api不被修改.

链接

将创建的类合成至Java虚拟机中,使之能够被执行的过程.它可以分为验证、准备及解析三个过程.

  • 验证阶段的目的是为了确保被加载的类满足虚拟机的约束条件.
  • 准备阶段的目的是为了被加载类的字段分配内存.
    • Java代码中对静态字段的具体初始化则会在稍后的初始化阶段进行.
    • 构造其它跟类层次相关的数据结构.比如说用来实现虚方法的动态绑定的方法表.
  • 解析阶段的目的是,将符号引用解析成为实际引用.
    • 如果符号引用指向一个未被加载的类、或者未被加载类的字段或方法,那么解析将触发这个类的加载(但未必触发这个类的链接以及初始化)

初始化

为标记为常量值的字段赋值,以及执行方法的过程.
java虚拟机会通过加锁来确保类的方法仅被执行一次.
只有当初始化完成之后,类才正式成为可执行状态.

类的初始化触发情况

  • 当虚拟机启动的时候,初始化用户指定的主类.
  • 当遇到用以新建目标类实例的new指令的时候,初始化new指令的目标类.
  • 当遇到调用静态方法时,初始化该类的静态字段.
  • 当遇到访问静态字段的指令时,初始化该静态字段所在的类.
  • 子类的初始化会触发父类的初始化.
  • 如果一个接口定义default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化.
  • 使用反射api对某个类进行反射调用时,初始化这个类.
  • 当初次调用MethodHandle实例时,初始化该MethodHandle指向的方法所在的类.

完…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值