JVM的类加载机制是指虚拟机
把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型的实现过程。
类加载过程具体可以分成下面几个步骤:
(1)装载:查找和导入Class文件;
(2)链接:把类的二进制数据合并到JRE中;
校验:检查载入Class文件数据的正确性;
准备:给类的静态变量分配存储空间,赋默认值;
解析:将符号引用转成直接引用;
(3)初始化:对类的静态变量,静态代码块执行初始化操作。
加载 Loading过程
加载是类加载过程的第一个阶段,
在加载阶段,虚拟机需要完成以下工作:
通过一个类的全限定名来获取其定义的二进制字节流;
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
在 Java 堆中生成一个代表这个类的 java.lang.Class 对象,作为对方法区中这些数据的访问入口。
注意,这里的二进制字节流并不只是单纯地从 Class 文件中获取,比如它还可以从 Jar 包中获取、从网络中获取、由其他文件生成(JSP 应用)等。
相对于类加载的其他阶段而言,加载阶段是可控性最强的阶段,因为开发人员既可以使用系统提供的类加载器来完成加载,也可以自定义自己的类加载器来完成加载。
加载阶段完成后,虚拟机外部的 二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在 Java 堆中也创建一个 java.lang.Class 类的对象,这样便可以通过该对象访问方法区中的这些数据。
(1)ClassLoader 类加载器
类加载器用于实现类的加载动作,但它在 Java 程序中起到的作用却不限于类的加载阶段。
对于任意一个类,都需要由它的类加载器和这个类本身一同确定其在就 Java 虚拟机中的唯一性,也就是说,即使两个类来源于同一个 Class 文件,只要加载它们的类加载器不同,那这两个类就必定不相等。
这里的“相等”包括了代表类的 Class 对象的 equals()、isAssignableFrom()、isInstance()等方法的返回结果,也包括了使用 instanceof 关键字对对象所属关系的判定结果。
Java 开发人员的角度来看,类加载器可以大致划分为以下三类:
启动类加载器,Bootstrap ClassLoader:
负责加载存放在JDK\jre\li(JDK 代表 JDK 的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如 rt.jar,所有的java.*开头的类均被 Bootstrap ClassLoader 加载)。
启动类加载器是无法被 Java 程序直接引用的。
扩展类加载器,Extension ClassLoader:
该加载器由sun.misc.LauncherExtClassLoader实现,它负责加载JDK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.∗开头的类),开发者可以直接使用扩展类加