类加载器概述
类加载器主要是在类的加载阶段起作用,所起的作用就是把在方法区中的类模板对象转化成.class对象。
类的加载可以分为显式加载和隐式加载两类:
- 显式加载,classLoader加载、class.forName加载
- 隐式加载,没有直接用加载器的代码进行加载
在内存中类的唯一性
在内存中类的唯一性不能仅仅用全类名进行区分,还要用类的加载器进行区分。同一个.class文件被不同的类加载器进行加载,那么这两个class对象也是不同的
类加载器的命名空间
每个类加载器都会有一个命名空间,命名空间是由这个类加载器以及其父类加载器所加载的全部.class对象所构成。同一个命名空间中,不会出现相同的类对象(.class对象)不同的命名空间可以存在全类名相同的两个类对应于内存中类的唯一性的定义规则;其实就是同一个在方法区中的类模板对象被不同的类加载器加载,所生成的类是不一样的。
类加载器的分类--方式1
引导类加载器
这类加载器指的是bootstrapClassloader是由c/c++语言实现的。
用户自定义加载器
这类加载器是由Java语言实现的类加载器。
在类加载器中有一个通俗的叫法是父类加载器是谁,但其实在实际的加载器中并不是一种继承关系,而仅仅是一种属性关系,可以看以下源码
public abstract class ClassLoader {
private static native void registerNatives();
static {
registerNatives();
}
// The parent class loader for delegation
// Note: VM hardcoded the offset of this field, thus all new fields
// must be added *after* it.
private final ClassLoader parent;
ClassLoader extcl;
try {
extcl = ExtClassLoader.getExtClassLoader();
} catch (IOException e) {
throw new InternalError(
"Could not create extension class loader", e);
}
// Now create the class loader to use to launch the application
try {
loader = AppClassLoader.getAppClassLoader(extcl);
} catch (IOException e) {
throw new InternalError(
"Could not create application class loader", e);
}
在上面的源码可以看出,在创建Appclassloader的时候把extcl加载器传进去了。
类加载器的分类--方式2
启动类加载器(bootstrapClassLoader)
这个加载器是由C++语言编写的,是最根本的类加载器,这个加载器加载应用类加载器和扩展类加载器。这个加载器是一个非常核心的、最“鼻祖”的加载器。
扩展类加载器(extensionClassLoader)
应用类加载器(applicationClassLoader)
自定义类加载器
这个加载器的父加载器是appclassloader