类加载过程总共下面几个步骤:
Java的动态扩展特性就是因为类的加载和连接是在程序运行过程中的。
加载(Loading):
加载在没有明确JVM规范,各个虚拟机自由处理。
加载要做的事情:
1.通过一个类的全限定名来获取定义此类的二进制字节流。
2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。
3.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区域数据的访问入口。
加载过程是相对其他类加载过程中是唯一开发阶段可控的,可以自定义类加载器来加载类。
验证(Varification):
确保Class文件符合当前的虚拟机规范和保证安全性
准备(Preparation):
正式为类变量分配内存(方法区内)和赋予“初始值”。注意这里的初始值不一定是Java程序赋予的那个初始值,例如
static int i = 3
,这个阶段的初始值是0,只有
static final int i = 3,这个阶段结束后,i的值才才回是3。
解析(Resolution):
虚拟机将常量池内存的符号引用替换为直接引用的过程。
初始化(Initialization):
类加载过程的最后一步,这里是真正开始执行类定义中的Java程序代码。
类加载器:
类的唯一性由类本身和加载该类的类加载器确定。也就是说,即使是同一个class文件,但是经由不同的类加载器加载,那么它们都是不一样的。,那么instanceof,equals等这些方法都受到影响。
从JVM角度看,类加载器有两种,一种是启动类加载器(C++实现),是虚拟机自身一部分,另外一种是其他(JAVA实现),独立于虚拟机外。
从程序员角度看,类加载器有多种,使用到的系统提供类加载的以下三种:
1.Bootstrap clasloader。加载<java_home>/lib或者被-Xbootclasspath指定路径的,并且是虚拟机识别的(仅按照文件识别,如rt.jar,名字不符合即使在lib也不会被加载),无法用java引用该类加载器。
2.Extension classloader。<java_home>/lib/ext的类和被java.ext.dirs系统变量指定的路径的类库。可以用java直接使用。
3.Application classloader。也称为系统类加载器。负载加载用户类路径(也就是我们经常在系统变量中定义的ClassPath)下的类库。用户可以直接使用,如果没有定义过自己的类加载器,一般情况下这个是默认的类加载器。
双亲委托模型:
一个类加载收到类加载请求,委托父亲去加载,除非父亲没有加载过才自己加载。
总结于:周志明《深入理解JAVA虚拟机》