JVM类加载器以及双亲委派模型

从java开发人员的角度来看,类加载器可以分为3种:

1、启动类加载器(Bootstrap ClassLoader),负责将存放在<JAVA_HOME>lib目录中,或者被-Xbootclasspath参数所指定的路径中,并且是虚拟机识别的类库加载到虚拟机内存中。

2、扩展类加载器(Extension ClassLoader),这个加载器负责<JAVA_HOME>libext目录中,或者被java.ext.dirs系统变量所指定的路径中的所有类库。

3、应用程序加载器(Application Classloader),负责加载用户类路径(ClassPath)上所指定的类库。如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

双亲委派模型是Java设计者推荐给开发者的一种类加载器实现方式(并不强制),其工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载任务的时候,子加载器才会尝试自己去加载这个类。

双亲委派模型带来的好处是,Java类随着它的类加载器一起具备了一种带有优先级的层次关系,例如Java.lang.Object类,都会在启动类加载器中被加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,应用程序将变得一片混乱。

双亲委派模型的实现逻辑:先检查是否已经被加载过,若没有被加载过,则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载器加载失败,抛出ClassNotFoundException后,在调用自己的findClass()方法进行加载。

具体代码:

protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
  {
      //首先,检查请求的类是否已经被加载过
      Class c = findLoadedClass(name);
      if(c == null) {
         try{
         if(parent != null){
             c = parent.loadClass(name, false);
         }else {
             c = findBootstrapClassOrNull(name);
         }
         }catch (ClassNotFoundException e) {
                //抛出异常,说明父类加载器无法完成这个请求
         }
         if(c == null){
             //调用本身的findClass来进行类加载
             c = findClass(name);
         }
}
if(resolve){
resolveClass(c);
}
return c;
}
原文地址:https://www.cnblogs.com/qiuhaojie/p/6932280.html