Java 虚拟机类加载的先后顺序是加载, 链接以及初始化三个操作.
引用类型在 Java 虚拟机中认为有三种, 接口, 类与数组类.
数据类是 Java 虚拟机直接生成的, 其他两种则有对应的字节流.
字节流最常见的形式是 Java 编译器生成的 class 文件. 除此之外可以在程序内部直接生成. 不同形式的字节流都会被加载到虚拟机哄, 称为类或者接口.
加载
加载: 查找字节流, 并根据此创建类的过程. 数组类能被 Java 虚拟机直接接受, 但是接口与类需要借助类加载器来完成查找字节流的操作.
除了启动类加载器之外, 其他的类加载器都是 ClassLoader 下子类.
需要先把启动类加载器加载到虚拟上才能加载其他类型的类加载器.
Java9 之前启动类加载器负责加载最为基础, 最为重要的类.
扩展类加载器的父类加载器是启动类加载器. 负责加载相对次要, 但又通用的类, 存放在 lib/ext 下面的 jar 包中的类.
应用类加载器的父类加载器则是扩展类加载器. 负责加载应用程序路径下的类. 系统变量, 或者环境变量, 虚拟机参数 - cp/-classpath, 三者下的类..
Java9 之后引入模块系统, 加载器进行了修改.
扩展类加载器改为平台类加载器, 除了少数几个关键模块是由启动类加载加载之外, 其他模块都是有平台类加载器加载.
可以引入自定义的加载器, 实现定制化的方式.
类的唯一性是由类加载器与类的全名两者一同确定的.
链接
指将创建成的类合并至 Java 虚拟机中, 是指能够执行, 分为验证, 准备, 以及解析三个阶段.
验证: 确保加载类能够满足 Java 虚拟机的约束条件.
准备: 为被加载类的静态字段分配内存. Java 代码中对静态字段的具体初始化, 则在初始化阶段进行.
解析: 编译会对一个方法的调用, 僧成一个包含方法所在类的名字, 目标方法的参数等等信息的符号引用, 来指代要调用的方法, 解析的目的是把符号引用解析称为真正的引用. 如果符号引用触发的是一个未被加载的类的字段或者类或者方法, 那么会触发类的加载. 但是未必会触发类的链接与初始化.
规范中没有要求了解的过程中完成解析, 使用了符号引用, 在执行字节码之前需要完成对符号引用的解析.
初始化
静态字段被 final 所修饰, 类型是基本类型, 或者字符串, 会被编译器编译为常量值, 初始化由虚拟机完成.
其他的赋值操作, 静态代码块中的代码被编译器置于同一个方法中 client 中.
初始化 操作是标记为常量值的字段赋值, 以及执行 clinit 的方法执行, 虚拟机通过加锁的手段保证 clinit 方法仅被执行一次.
来源: http://www.jianshu.com/p/129d03bc04ec