类加载机制

前言

在java语言里面,jvm把类的数据从class文件加载到内存,并对数据进行校验,转换解析,初始化;而在类型的加载,连接,初始化过程都是在程序运行期间完成的,这种方式提高了应用程序的灵活性。

类的生命周期 此处输入图片的描述 整个过程除了解析阶段,其他阶段都是相互交叉混合的执行,通常会在一个阶段执行过程中调用,激活另一个阶段

必须立即对类进行“初始化”情况 jvm规范规定下面几种情况必须立即对类进行初始化

接口的初始化大致和类一致,在对父接口初始化的时候,不要求父接口全部完成初始化,只是在真正使用到了父接口的时候才会初始化。

加载

加载过程分为三个过程

第一步,获取二进制流可以通过很多方式进行获取,jar,war,ear包,网络,代理都可以获取

数组类型类加载时,如果组件类型是引用类型,则会使用该组件类型的类加载器进行加载;如果是基本类型,则会使用引导类加载器进行加载

验证

Java虚拟机只与Class文件这种特定的二进制文件格式所关联,使用java语言编写代码会在编译的时候对数组边界,类型转换,跳转等代码进行验证,但是如果是采用其他语言编写,编译成class文件就有可能没有经过一定的验证,造成载入系统奔溃的代码。

主要验证动作

准备

主要是为类变量分配内存并初始化值,这里指的初始化是指基本类型的初始化,都是该数据类型零值。(final修饰常量为指定的常量值)

解析

主要是将常量池中符号引用替换为直接引用

虚拟机实现根据需求判断是在类加载时进行解析,还是等到被使用前才进行解析。 解析动作主要针对类或接口,字段,类方法,接口方法,方法类型,方法句柄和调用点限符进行符号引用。

类或接口的解析 以当前代码所处D类中,要把一个从未解析过的符号N解析为一个类或接口C的直接引用。

字段解析 字段解析会经过对字段所属的类或接口进行解析,得到C,完成后进行下面步骤:

同样会对返回引用进行权限验证。

如果同名字段同时出现在C的接口,父类中或同时在自己和父类多个接口中出现,编译器会拒绝编译

类方法解析 和字段解析一样,需要先解析出方法所属类或接口的符号引用,解析完成,得到C,然后进行下面步骤:

当然最后会对该方法引用进行权限验证

接口方法解析 和类方法解析一样,先解析出方法所属类或接口的符号引用,解析完成,得到C,然后进行下面步骤:

初始化

在初始化阶段,才真正执行类中定义的java程序代码,用另外一种角度表达,这个阶段是执行类构造器方法的过程。

##类加载器 类加载器主要实现了在类加载阶段,通过一个类的全限定名来获取描述此类的二进制字节流,这个实现动作是放到java虚拟机外部去实现的。

每一个类,都需要由加载它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性。

双亲委派模型

此处输入图片的描述 从java虚拟机角度来看,只存在两种不同类加载器:

从开发角度来看,可分为以下三种:

双亲委派模型工作过程是如果一个类加载器收到类加载请求,首先不会自己去尝试加载这个类,而是将加载请求委派给父类加载器,如果父类无法加载该请求,才自己去尝试加载。

双亲委派模型确保了java程序的稳定运作,避免了自定义类和基础类由于全限定名的一样导致的关系错乱,保证了java类型体系的行为。

双亲委派模型破坏,程序动态性,osgi,jndi