一、通过3个步骤:加载、连接、初始化完成对类的加载。类的加载由类加载器完成。
1类的加载
类加载器通常由JVM提供,JVM提供的这些类加载器通常被称为系统类加载器,因此可以通过继承ClassLoader基类来创建自己的类加载器。类加载器将生成一个对应的Class对象,通常无需等到“首次使用”该类时才加载该类,Java虚拟机规范允许系统预先加载某些类。
2类的连接
当类被加载之后,系统为之生成一个对应的Class对像,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中。连接分为三个阶段:
1、验证:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致。
2、准备:负责为类的静态Field分配内存,并设置默认初始化值。
3、解析:将类的二进制数据中的符号引用替换成直接引用。
3类的初始化
在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对静态Field进行初始化。在java类中对静态Field指定初始值。还有,JVM初始化一个类包含如下步骤:1)加入这个类还没有被加载和连接,则程序先加载并连接该类。2)假如该类的直接父类还没有被初始化,则先初始化其直接父类。3)假如类中有初始化语句,则系统一次执行这些初始化语句。当执行第二个步骤时,系统对直接父类的初始化步骤也遵循此步骤1到3,以此类推。所以,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类 时,系统会保证该类以及所有父类(包括直接父类和间接父类)都会被初始化。
二、类初始化时机
当java程序首次通过下面5种方式来使用某个类或接口时,系统就会初始化该类和接口。
1)创建类的实例,分三种:使用new操作符创建、通过反射创建、通过反序列化创建
2)调用某个类的静态方法
3)访问某个类或接口的静态Field,或为该静态Field赋值。
4)初始化某个子类,则该子类的所有父类都会被初始化。
5)直接使用java.exe命令来运行某个主类,程序会先初始化该类。
对于一个finally型的静态Field,如果该Field的值在编译时就可以确定下来,那么这个Field相当于“宏变量”---即java编译器会在编译时直接把这个Field出现的地方替换成它的值。因此程序使用该静态Field,也不会导致该类的初始化。如果final型的静态Field的值不能在编译时确定(需要运行程序时,才能确定值),则该类访问这个fianl型静态Field,会导致该类被初始化。
当使用ClassLoader类的loadClass()方法来加载某个类时,该方法知识加载该类,并不会执行该类的初始化方法。使用Class的forName()静态方法才会导致强制初始化该类。
附:参考文章 《疯狂java讲义》