1. ClassLoader
类加载器 是一个负责 加载 类的 对象,ClassLoader 类 是一个抽象类 。
给定一个类的 二进制名称 ,一个类加载器 应该尝试 定位 或 生成 构成类定义的数据;
解释: 二进制名称举例如下:
"java.lang.String"
"javax.swing.JSpinner$DefaultEditor"
"java.security.KeyStore$Builder$FileBuilder$1"
"java.net.URLClassLoader$3$1"
每个 Class 对象 都包含 一个 获取 ClassLoader 的 方法 。方法为 getClassLoader();
类 加载器 没有 创建 数组类 的 Class 对象,但是 在 java 运行时期 会 按需 自动 被 创建。 一个 数组类 调用 getClassLoader()返回 的 类加载器 和 数组中的元素 的 类加载器相同;如果 数组中存储的 是 基本数据类型,则 数组类 没有 类加载器;
应用实现 ClassLoader 的子类 是 为了 扩展 jvm 虚拟机 动态加载 类的 方式;
ClassLoader 类 使用 委托模式 查询类和资源 。 每个 ClassLoader 的 实例 都有一个 相关联的 父 类加载器 。 当 请求加载 类 或者 资源时,一个 ClassLoader 实例 会在 自己尝试找出 类或者资源 之前, 委托 它的父 类加载器 搜索 类或者资源 。 虚拟机的内置 类加载器 ,叫做 bootstrap class loader (类加载器的顶层),它自己没有 parent ,但是可以给 其他的 ClassLoader 实例 充当 父 加载器。
支持 并行加载 类的 类加载器 称为 可并行类加载器(parallel capable class loaders),这类类加载器需要在类初始化时 调用 registerAsParalleCapable() 。ClassLoader 类 默认注册并行 加载,但是它的子类如果是 并行类加载器的话 还需要注册 。
通常, Java 虚拟机 以 一种依赖平台的方式 从 本地文件系统中 加载 类。例如, UNIX 系统中 , 虚拟机 通过 定义的 classpath 环境变量 从目录中 加载类。
然而,一些类 可能不是 来源于 文件 ,他们可能 来源于其他的 资源,比如 网路,或者 他们可以 根据一个应用 构造出来。 defineClass(String name, byte[] b, int off, int len) 方法 可以 将 字节数组 转为类 Class 的一个实例,然后 使用 newInstance 方法 实例化。
2. 参看好文章
xyang0917 的 深入分析Java ClassLoader原理
3. 附
Spring framework ClassUtils 类 中 获取 默认 ClassLoader 的 静态方法源码
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
if (cl == null) {
// No thread context class loader -> use class loader of this class.
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
如果上面的方法 仍然 获取不到 ClassLoader ,Spring 直接使用
Class.forName(String className)