类加载器
类加载器负责将.class文件加载到jvm中运行,java内置三种类加载器,除内置类加载器外,还可以自己实现类加载器。
BootstrapClassLoader:启动类加载器,加载 jre/lib 目录下的核心类库
ExtClassLoade:扩展类加载器,加载 jre/lib/ext 目录下的文件
AppClassLoader:应用程序类加载器负责加载classpath下字节码文件
CustomClassLoader: 自定义类加载器,遵循双亲委派机制需要继承ClassLoader重写findClass方法自定义读取文件。违背双亲委派机制同样需要继承ClassLoader重写ClassLoader方法破坏加载顺序
类加载器加载路径可通过如下代码进行验证
System.out.println("BootstrapClassLoader加载路径------------------------------------------------------");
URL[] urls = Launcher.getBootstrapClassPath().getURLs();
for (URL url : urls) {
System.out.println(url);
}
System.out.println("ExtClassLoade加载路径------------------------------------------------------");
URLClassLoader extClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader().getParent();
urls = extClassLoader.getURLs();
for (URL url : urls) {
System.out.println(url);
}
System.out.println("AppClassLoader加载路径------------------------------------------------------");
URLClassLoader appClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
urls = appClassLoader.getURLs();
for (URL url : urls) {
System.out.println(url);
}
双亲委派机制
双亲委派机制工作流程:
1.类加载器收到加载请求不会由自己加载,而是把加载请求让父类执行
2.父类收到加载请求判断是否还有父类,有的话继续让父类执行
3.递归执行步骤2,直到没有父类,也就是到BootstrapClassLoader类加载器
4.父类加载器判断是否能加载,能加载则成功返回,不能加载则让子类去加载
5.依次执行步骤4,对类进行加载,直到最下层类加载器,如果不能加载则抛出异常
采用双亲委派机制优势在于
1.避免类重复加载:加载时向上委托,如果加载过就不在加载
2.防止核心类被篡改:例如我自定义了一个java.lang.Integer类修改其实现方法, 没有双亲委派机制则会加载两个Integer类,造成系统混乱