- java.lang.ClassLoader 抽象类,根据类名称,找到类的字节码,加载类,生成Class对象,获取类资源如配置文件
- 引导加载类(bootstrap class loader)
- 扩展类加载库(extension class loader)
- 应用程序类加载器(application class loader)
- 自定义类加载器
他们之间的关系是树形结构,但不是继承关系,而是组合使用关系
public class Demo02 {
public static void main(String[] args) {
System.out.println(ClassLoader.getSystemClassLoader());//当前使用的类加载器System.out.println(ClassLoader.getSystemClassLoader().getParent());
//父亲类加载器,这个父亲指的是属性结构的父亲,不知继承关系
System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());System.out.println(System.getProperty("java.class.path"));//当前类加载path的路径
}
输出
}
类加载器的代理模式
双亲委托机制(代理模式的一种)
某个特定的类加载器在接到加载类的请求时,将任务委托给父类(树结构的父类)加载器,直到根节点的类加载器,如果该加载器无法加载类,再一层一层向下加载,直到加载成功,就返回。保证了Java核心库的类型安全,类加载器除了用于加载类,也是最安全的保障。比如java.lang.String类是java的核心类库,你要加载一个String类,采用双亲委托机制就会确保你加载到java核心类库的String类,而不是会有人自己定义的路径为java.lang.String类。
但是并不是所有的类加载器都是用双亲代理模式机制,Tomcat服务器类加载器也是用代理模式,只是不是双亲委托机制,而是自己先去加载,加载不了,再给父类。
线程上下文类加载器
抛弃双亲委托机制,每一个线程都有一个关联的上下文类加载器,默认是系统类加载器,可以用下面第二个方法进行更改,比如更改为自定义的类加载器。
Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader();