Java中有四类加载器。
- BootStrap ClassLoader:启动类加载器,加载\lib目录下的符合特定名字的jar包
- Extention ClassLoader: 扩展类加载器,加载\lib\ext目录下扩展的jar包
- Application ClassLoader:应用程序类加载器,加载指定的classpath下面的jar包
- Custom ClassLoader:自定义的类加载器
而加载Class类的顺序是有优先级的,这就是类加载器的双亲委派机制
双亲委派机制的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。
一般在加载器的构造函数中可以指定父加载器
protected ClassLoader(ClassLoader parent)
没指定则默认父加载器为AppClassLoader ,指定为null父加载器则为BootstrapClassLoader。
而本文要介绍的urlclassloader是继承自classloader
urlclassloader可以指定一串路径,然后在路径下面寻找要加载的类。这个类加载器如果没有指定的话父类加载器也是AppClassLoader
举例:我们将HelloWorld.class文件放于:N:/
public class HelloWorld {
public HelloWorld(){
System.out.println("Hello World");
}
}
通过urlclassloader去加载这个类
public class UrlclassloaderTest {
@Test
public void urlclassloader() throws Exception{
File file = new File("N:/");
URL url = file.toURI().toURL();
ClassLoader loader = new URLClassLoader(new URL[]{url});
Class<?> clazz = loader.loadClass("HelloWorld");
System.out.println("当前加载器"+clazz.getClassLoader());
System.out.println("父类加载器"+clazz.getClassLoader().getParent());
clazz.newInstance();
}
}
在构造方法中没有指定父类加载器,所以默认为AppClassLoader
如果在当前的classpath也放置一个Hello.class文件,那么就会被APPClassLoader加载,而且加载不到N盘的那个文件
public class HelloWorld {
public HelloWorld(){
System.out.println("this is annother Hello World");
}
}
如果把URLClassLoader的父类加载器设置为BootStrap加载器,就可以避免AppClassLoader加载classpath下的同名文件。
public URLClassLoader(URL[] urls, ClassLoader parent)
只需要将parent设为null,这样父加载器就是BootStrap加载器