一、概念
“通过一个类的全限定名来获取描述此类的二进制字节流”,实现这个动作的代码模块成为 类加载器。
二、分类
从java开发人员的角度出发,系统提供的类加载器大致分为如下3类:
1、启动类加载器(Bootstrap ClassLoader)
负责将存放在<JAVA_HOME>/lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中;
2、扩展类加载器(Extension ClassLoader)
负责加载<JAVA_HOME>/lib/ext目录中的,或者被java.ext.dirs系统变量指定的路径中的类库,开发者可以直接使用;
3、应用程序类加载器(Application ClassLoader)
负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用
4、双亲委派模型
1)定义:除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,且加载器之间的父子关系一般不会继承,而是使用组合关系来复用父加载器的代码。
2)工作过程:
如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(搜索范围内找不到所需的类)时,子加载器才会尝试自己去加载。
3)实现:
protected synchronized Class<?> loadClass(String name,boolean resolve) { //首先查看请求类是否已被加载过 Class c = findLoadedClass(name); if(c == null){ try{ if(parent != null){ c = parent.loadClass(name,false); } else{ c = findBootstrapClassOrNull(name); } }catch (ClassNotFoundException e){ //父类加载器无法完成加载请求 } //父类无法加载时在调用本身的findClass来进行类加载 if(c == null){ c = findClass(name); } } if(resolve){ resolveClas(); } return c; }
步骤解析:
先检查是否已经被加载过,若没有则调用父加载器的loadClass()方法,若父加载器为空则默认是使用启动类加载器作为父加载器,若父类加载失败,抛出ClassNotFoundException后,再调用自己的findClass()方法进行加载。