类加载机制---概述和类加载的时机
一、概述
1. 虚拟机加载机制
把描述类的数据从class文件加载到内存,并且对数据进行校验、转换解析和初始化,最终形成可以被虚拟机使用的Java类型。
2. Java是一门天生可以动态扩展的语言
在Java语言里,类的加载、链接和初始化是在程序运行期间完成的。而C++是在编译期就开始做这些工作了。
这种策略在类加载的时候,增加了一些内存开销。但是为Java程序提供了极高的灵活性。
根据动态加载和动态链接,实现了Java语言的动态扩展。
譬如: 根据预定义或者自定义的类加载器,可以加载互联网上的一个class文件,然后执行该字节码。
二、 类的加载时机
1. 生命周期
类被加载到虚拟机内存中开始,到卸载出内存位置,生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading) 7个阶段。其中, 验证、加载和解析这3个阶段称为 连接。
2. 运行时绑定(动态绑定或者晚期绑定)
加载、验证、准备、初始化、卸载这5个阶段的顺序不会变的。虚拟机必须按照这个顺序来开始。
但解析阶段则不一定,某一些情况下在初始化之后才解析阶段才开始,这是要支持java语言的运行时绑定。
这些阶段,并不是一个阶段执行完了再执行下一个阶段,而是交替着混合着执行。可能在一个阶段中调用、激活另外一个阶段。
3. 初始化的条件
只有当满足下面5个条件之一才会执行初始化。
(1)遇到 new、getstatic、putstatic或invokestatic 这四个关键字,如果类没有初始化,就需要先初始化。
new: 使用new关键字
getstatic和putstatic: 读取或设置一个静态字段(带final或已经在编译期把常量放到常量池的静态字段除外。)
invokestatic: 调用一个类的静态方法
(2)对类进行反射调用的时候,如果没有初始化,就先初始化。
(3)初始化一个类,如果其父类没有初始化,就初始化父类。
(4)虚拟机启动时,指定一个主类(main方法的类),会先初始化这个主类。
(5)jdk1.7中, 如果一个 java.lang.invoke.MethodHandle实力最后的解析结果 REF_getstatic REF_putstatic REF_invokestatic的方法句柄,并且这个方法句柄所对应的类没有初始化,就先初始化。