[JAVA] ClassLoader双亲委派模式作用详解

1917 0
黑夜隐士 2022-11-8 17:38:58 | 显示全部楼层 |阅读模式
目录

    前言ClassLoader的作用ClassLoader的种类如何实现双亲委派模式小测试


前言

我们的面试中经常会遇到关于ClassLoader的问题,但是我们的日常开发中又没有直接编写过ClassLoader相关的代码。对于小白新手来说,可能都不知道ClassLoader是用来干嘛的,它是如何在无形当中影响我们编写的代码的?

ClassLoader的作用

见名知意,ClassLoader就是类加载器,它的作用就是将我们编写的java代码加载到JVM虚拟机中。在JVM启动的时候是不会一次性把所有的java类加载进去的,而是在需要的时候才加载指定的类文件,要不然类特别多的话,大部分类一时用不上,那就浪费内存资源了。既然ClassLoader是用来加载类文件的,那么我们平时写的java代码是如何加载的呢?

ClassLoader的种类

在JDK中,默认是有三种ClassLoader的:
Bootstrap ClassLoader
主要加载核心类库,加载${JRE_HOME}/lib下的rt.jar、resources.jar等;
Extension ClassLoader
加载扩展类库,加载${JRE_HOME}/lib/ext文件夹下的jar包和class文件;
另外还会加载-D java.ext.dirs指定的目录下的jar包和class文件;
AppClassLoader
加载当前应用classpath下的所有class文件;

如何实现双亲委派模式

在Launcher类中,我们可以看到Launcher创建的时候,同时创建了ExrClassLoader与AppClassLoader对象。
sun.misc.Launcher:
  1.     public Launcher() {
  2.         Launcher.ExtClassLoader var1;
  3.         try {
  4.             var1 = Launcher.ExtClassLoader.getExtClassLoader();
  5.         } catch (IOException var10) {
  6.             throw new InternalError("Could not create extension class loader", var10);
  7.         }
  8.         try {
  9.             this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
  10.         } catch (IOException var9) {
  11.             throw new InternalError("Could not create application class loader", var9);
  12.         }
  13.         Thread.currentThread().setContextClassLoader(this.loader);
  14.     }
复制代码
1.创建ExtClassLoader对象;
2.创建AppClassLoader对象,并把ExtClassLoader对象作为AppClassLoader的父级ClassLoader;
3.把AppClassLoader对象绑定到线程上下文中;
为什么没有提到BoostrapClassLoader?
因为BoostrapClassLoader在java层面是拿不到的,ExtClassLoader的父级ClassLoader就是BoostrapClassLoader,java层面取出来就是null;
为了了解清楚类的加载方式,我们首先需要从AppClassLoader中的loadClass()方法中入手:
  1. protected Class<?> loadClass(String name, boolean resolve)
  2.         throws ClassNotFoundException
  3.     {
  4.         synchronized (getClassLoadingLock(name)) {
  5.             // 首先, 检查这个类是否已经加载好了
  6.             Class<?> c = findLoadedClass(name);
  7.             // 如果没有加载过
  8.             if (c == null) {
  9.                 long t0 = System.nanoTime();
  10.                 try {
  11.                     // 如果父级ClassLoader不为空,那么就先尝试让父级ClassLoader加载
  12.                     if (parent != null) {
  13.                         c = parent.loadClass(name, false);
  14.                     } else {
  15.                         // 如果父级ClassLoader为空,有可能父级ClassLoader是BootstrapClassLoader,那么先尝试在BootstrapClassLoader加载
  16.                         c = findBootstrapClassOrNull(name);
  17.                     }
  18.                 } catch (ClassNotFoundException e) {
  19.                     // ClassNotFoundException thrown if class not found
  20.                     // from the non-null parent class loader
  21.                 }
  22.                 // 如果一直向上都没有加载目标class,那么最终回到当前ClassLoader加载
  23.                 if (c == null) {
  24.                     // If still not found, then invoke findClass in order
  25.                     // to find the class.
  26.                     long t1 = System.nanoTime();
  27.                     c = findClass(name);
  28.                     // this is the defining class loader; record the stats
  29.                     sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
  30.                     sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
  31.                     sun.misc.PerfCounter.getFindClasses().increment();
  32.                 }
  33.             }
  34.             if (resolve) {
  35.                 resolveClass(c);
  36.             }
  37.             // 返回加载成功的类
  38.             return c;
  39.         }
  40.     }
复制代码
通过以上代码分析,我们可以大概了解到双亲委派模式了:
1.先在当前ClassLoader检查是否已经加载了目标类;
2.如果当前ClassLoader没有加载目标类,那么先向尝试让父级ClassLoader加载目标类,直至BootstrapClassLoader;
3.如果最终所有的父级ClassLoader都没有加载目标类,那么当前ClassLoader尝试自己加载目标类;
4.所有父级ClassLoader重复操作1~3步骤;
5.只要其中任意一个ClassLoader成功加载目标类,那么就直接返回;

小测试

为了验证小伙伴们是否已经明白了双亲委派模式,我们出一个小小的测试题留给大家:
我们通过自己创建一个java.lang.String的类(类名和包名和JDK中的String.class一致),这个自定义的String类能不能通过AppClassLoader成功地加载到JVM中?
以上就是ClassLoader双亲委派模式作用详解的详细内容,更多关于ClassLoader双亲委派模式的资料请关注中国红客联盟其它相关文章!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行