JVM基础知识整理(二)双亲委派机制

编程

         JVM的类加载的有个关键的设计就是双亲委派 Parents delegate ,理解了双亲委派,也就较好理解了类加载的精髓。JVM提供了三种系统加载器:

  1. 启动类加载器(Bootstrap ClassLoader):负责加载<JAVA_HOME>/lib下的类库,如Java基础类库 rt.jar(包括了Math、IO、String等类),开发者无法获取该加载器。
  2. 扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>/lib/ext下的类库,开发者可以直接使用。
  3. 应用程序类加载器(Application ClassLoader):负责加载用户程序、应用包所引用的类库,开发者可以直接使用,是程序中默认的类加载器。

        如有必要,还可以自定义类加载器,继承ClassLoader覆写findClass(name)和findResource()即可,如果我们需要引入的类库不在默认的classPath下/从网络读取类/热部署等,这时就需要对加载类过程进行特殊处理,则可通过自定义类加载器实现。

        获取classloader程序示例如下:

		// 自定义类

ClassLoader aa = Test.class.getClassLoader();

System.out.println(aa);

// ext目录下jar中的类

ClassLoader bb = ECKeyFactory.class.getClassLoader();

System.out.println(bb);

// lib目录下rt.jar中的类

ClassLoader cc = String.class.getClassLoader();

System.out.println(cc);

         运行结果:

sun.misc.Launcher$AppClassLoader@73d16e93

sun.misc.Launcher$ExtClassLoader@6bc7c054

null

          这些类加载器的层级关系就构成了双亲委派模型。双亲委派模型工作流程:

1.当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成。
2.当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器BootstrapClassLoader去完成。
3.如果Bootstrap ClassLoader加载失败(在<JAVA_HOME>lib中未找到所需类),就会让Extension ClassLoader尝试加载。
4.如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载。
5.如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。

       根据该工作流程可以发现,Parents delegate翻译为双亲委派确有道理,双亲指的就是Extension ClassLoader和Bootstrap ClassLoader, JVM设计了双亲委派的目的就在于避免类重复加载 、避免核心API被篡改,如果没有双亲委派,那同名类的加载就会显得一片混乱所以当编写了一个与rt.jar的lang包同名的String类时,JVM始终会调用启动类加载器中的String的方法,而不去执行自定义的String。

      但是某些情况下篡改核心API还是可以被篡改,如JDBC的Driver接口,为了不加载父类的driver接口,通过线程获取上下文类加载器ContextClassLoader
(Thread.currentThread().getContextClassLoader())
,然后通过ContextClassLoader请求子类加载器完成类加载。

 

以上是 JVM基础知识整理(二)双亲委派机制 的全部内容, 来源链接: utcz.com/z/518745.html

回到顶部