【Java】类加载机制

本文详细介绍了Java类加载过程,包括加载、验证、准备、解析和初始化五个阶段,并解释了类加载的时机及其在虚拟机中的作用。

1.概述

类加载指的是把class文件载入到内存,并创建运行时数据的过程。一个类的生命周期为:

加载 连接 初始化 使用 卸载。其中的连接又可以分为三部分,验证 准备 解析。

2.类加载的时机

在以下四种情况下会触发类加载:

(1)实例化一个对象或者使用类变量或者调用类方法时,类没有被加载;

(2)使用反射,类没有被加载;

(3)初始化类时,其父类没有被加载,那么就需要加载父类;

(4)主类,即包含main入口的类

3.加载

该过程主要做两件事:

(1)使用类加载器根据全类名把class文件独到内存中

(2)创建Class对象,该对象的位置没有明确规定,可以在堆区,也可以在方法区。

4.验证

因为class文件可以来源于任何地方,我们甚至可以手动生成一个,所以虚拟机必须检测其格式是否正确,以防对虚拟机造成损害。验证主要涉及一下四方面内容:

(1)格式:魔数,版本号以及表类型

(2)元数据:语义级别,比如final的类不能被继承

(3)字节码:分析控制流,看执行会不会有问题

(4)符号引用:能否找到,可见性等

5.准备

这个阶段主要为Class实例的变量分配空间并设置初始值,注意这里的初始值全被被设置为0。与类构造方法不同。

比如static int a = 123;那么在准备阶段只是设置a的值为0,在类的构造器中,才会为其赋值123。类的构造器是什么?是虚拟机自动生成的为类变量赋值的方法,比如静态块或者显式的赋值(就像这里的123)。

6.解析

把一个class文件加载进来以后,方法体内部的变量全部是符号引用,也就是指向了常量池里的变量名字符串,此时还没有定位到内存中的其他区域。解析就是把符号引用替换为直接引用的过程。直接引用才与虚拟机的内存相关。

解析主要针对以下七种符号引用:

类或接口,字段,类的方法,接口的方法,方法类型,方法句柄和调用点限制。

下面先来看前三种

(1)类或接口,java是强类型语言,所有变量必须先声明再使用,申明的的过程就会指明类名,所有设计类型或者接口的地方都会生成一个Class_info的常量池项目。这里就是对这类符号进行解析。假设当前的类为A,A的方法内部有一个B的实例,那么虚拟机最后就需要解析这个B。

如果B不是数组类型,就会用A的类加载器按照B的全限定类名来定位B的class文件位置,进行加载,当然也要有验证准备等阶段。如果B是数字类型,就加载数组中元素的class,一旦加载完毕,还需要检测访问权限,如果没有,那么就抛出IllegalAccessError异常。最后常量池的服药引用会与B的class对象关联起来。

(2)字段,源文件中的任何字段,包括自己定义的和使用别的类的,都会生成一个Fieldref_info常量项目。要解析一个字段,首先需要解析字段所在的类或者接口,然后才能解析字段。假设该字段所在的类为C,已经解析,那么首先看C里面是否有该字段,如果有,那么结束。否则看C实现的接口内部是否有,否则再看C的父类是否有(递归),如果都没有抛出一个异常。

(3)方法,解析但是Methodref_info常量。首先解析对应的类型,假设为C。然后先看C是否有,若没有看C的父类是否有,若没有看C的父类接口或者C的接口中是否有,如果接口有,那么说明没有实现,抛出一个异常。

总体而言,解析与class文件格式息息相关,class文件格式中的常量池有14种类型的常量,class中的任何名称都会被放入常量池中,解析其实就是将对常量池中的字面量转换为直接引用的过程。到目前为止,我们就明白了类型级别的解析过程,就是把当前class中用到的全部外部的类型或者字段方法全部定位到内存中其他的Class实例。当时与变量相关的解析还没有进行。

总体而言,类加载就是把一个class文件载入内存中,然后创建一个Class实例,并且解析内部的符号的过程。

7.初始化

这一步之前,并没有执行任何程序员编写的代码,都是虚拟机自己主导的,到初始化阶段才会开始执行用户自定义的代码。这个阶段主要是为类变量赋值的,执行类的构造方法<cinit>。

那么<cinit>如何生成?

虚拟机会收集所有类变量的赋值语句以及静态块然后自动生成<cinit>,程序员并不会感知这件事。关于<cinit>,在多线程环境下是需要注意的,虚拟机会加锁,同步,保证多个线程同时初始化一个类时,只有一个线程可移植性<cinit>方法,其余的方法会被阻塞。这就是使用静态内部类实现单例的原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值