类的加载过程
JVM将类的加载过程分为:
-
装载(Load)
查找并加载类的二进制数据。
-
链接(Link)
-
验证
保证加载类的正确性。
-
准备
给类的静态变量分配内存空间,并将其初始化为默认变量。
-
解析
把类中的符号引用转变为直接引用。
-
-
初始化(Initialize)
为类的静态变量赋正确的初始化值。
示意图:
类的初始化
以下情况会被初始化:
- 创建类的示例,即new一个对象;
- 访问某个类的静态变量或者给该类的某一静态变量赋值;
- 调用类的静态变量;
- 使用反射机制加载某个类;
- 初始化某个子类(其父类也会被初始化);
- 在JVM启动时被标明的启动类,即命令行参数的指定的类;
类的初始化步骤为:
- 如果这个类还没有被加载和链接,那先加载和链接;
- 如果这个类存在直接父类,而这个父类并没有被初始化,便先初始化父类;
- 如果类中存在初始化语句(static变量和static块),就依次执行这些初始化语句块;
类的加载
类的加载有如下步骤:
- 将类型编译后的.class文件读到内存中;
- 将读出的数据放到运行时数据的方法区内;
- 在堆内存中创建这个类的Class对象,用来封装这个类在方法区内的对象;
类的加载最终结果就是堆内存中的Class对象。
Class对象封装了类在方法区内的数据结构。
加载器
JVM的类加载是通过类加载器(ClassLoader)来完成的。
主要有如下几种加载器:
-
Bootstrap ClassLoader
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class。
-
Extension ClassLoader
负责加载Java平台中扩展的一些功能包。
-
App ClassLoader
负责加载classpath指定的jar包及class。
-
Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader,加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类在所有ClassLoader只加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
双亲委派机制
双亲委派机制是指:某个特定的类加载器在收到加载类的请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,则返回成功;如果父类加载器无法完成任务时,才会自己去加载。