类加载
类加载器
BootStrapClassLoader
(启动类加载器) : 负责加载java 的核心类库: lib\rt.jar等ExtensionClassLoader
(扩展类加载器) : 加载扩展类库 : JAVA_HOME\lib\ext等ApplicationCalssLoader
(应用程序加载器) : 加载用户路径下ClassPath下的类包用户自定义加载器
: 加载用户自定义的包下的类(例如: Tomcat)
类加载的生命周期
加载: 通过io读入字节码文件(.class
)
“加载”过程主要是靠类加载器实现的,包括用户自 定义类加载器。类加载过程的一个阶段,ClassLoader通过一个类的完全限定名查找此类字节码文件,并利用字节码文件创建一个Class对象
(这也是类加载的终极目的)。
连接(可分为三个步骤):
- 验证: 目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身的安全,主要包括四种验证:
文件格式的验证
,元数据的验证
,字节码验证
,符号引用验证。
- 准备:为static成员分配内存 1.7之前在方法区中,1.7之后在堆中,并且初始化 0 值
- 解析:把常量池中的符号引用 --> 直接引用.
初始化:这是类加载的最后阶段: 调用类初始化方法
的过程,完成对 static 修饰的类变量的
手动赋值还有主动调用静态代码块。如果该类具有父类就进行对父类进行初始化,执行其静态初始化器(静态代码块)和静态初始化成员变量。(前面已经对static 初始化了默认值,这里我们对它进行赋值,成员变量也将被初始化)
然后就是: 使用和卸载了
双亲委派机制
源码
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
// -----??-----
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先,检查是否已经被类加载器加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// 存在父加载器,递归的交由父加载器
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 直到最上面的Bootstrap类加载器
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {