理解ClassLoader:

本文详细介绍了Java中的BootstrapClassLoader、ExtensionsClassLoader、ApplicationClassLoader和自定义ClassLoader,以及双亲委托模式的工作原理。同时对比了Android中的BootClassLoader、DexClassLoader和PathClassLoader,展示了它们在类加载过程中的角色和差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

Java中的ClassLoader:

1.ClassLoader的类型: 

1.1:Bootstrap ClassLoader(引导类加载器):

1.2:Extensions ClassLoader(拓展类加载器):

1.3:Application ClassLoader(应用程序类加载器):

1.4:Custom ClassLoader:

2.ClassLoader的继承关系:

3.双亲委托模式:

3.1:总结:

4.自定义ClassLoader:

Android中的ClassLoader:

1.ClassLoader的类型:

1.1:BootClassLoader:

1.2:Dex ClassLoader:

1.3:Path ClassLoader:

2.ClassLoader的继承关系:

3.ClassLoader的加载过程:

4.BootClassLoader的创建:

5.Path ClassLoader的创建:


 

Java中的ClassLoader:

 

Java的类加载器,它的主要作用就是通过多种类加载器来查找和加载class文件到Java虚拟机中。

 

 

1.ClassLoader的类型: 

 

Java的类加载器主要有两种类型,即系统类加载器和自定义类加载器。其中系统类加载器包括3种,分别是:Bootstrap ClassLoader(引导类加载器),Extensions ClassLoader(拓展类加载器),Application ClassLoader(应用程序类加载器)。

 

 

1.1:Bootstrap ClassLoader(引导类加载器):

用C/C++代码实现的加载器,用于加载指定的JDK的核心类库。Java虚拟机的启动就是通过引导类加载器创建一个初始类来完成的。该加载器不能被Java代码访问到,但是可以查询某个类是否被引导类加载器加载过。需要注意的是Bootstrap ClassLoader并不是继承java.lang.ClassLoader。它可以加载:

  • $JAVA_HOME/jre/lib目录。
  • -Xbootclasspath指定的目录。

 

 

1.2:Extensions ClassLoader(拓展类加载器):

Java中的实现类为ExtClassLoader,用于加载Java的拓展类,提供除了系统类之外的额外功能。ExtClassLoader可以用来加载:

  • 加载$JAVA_HOME/jre/lib/ext/目录。
  • 系统属性java.ext.dir所指定的目录。

 

 

 

1.3:Application ClassLoader(应用程序类加载器):

Java中的实现类为AppClassLoader,也叫做系统类加载器(System ClassLoader),这个类加载器可以通过ClassLoader的getSystemClassLoader方法获取到。它可以加载:

  • 当前程序的classpath目录。
  • 系统属性java.class.path指定的目录。

 

 

 

1.4:Custom ClassLoader:

除了系统提供的类加载器外,我们还可以自定义类加载器,自定义类加载器通过继承java.lang.ClassLoader类的方式来实现自己的类加载器。

 

 

2.ClassLoader的继承关系:

2b03142408ea46d3a81abaa3eea66e7a.png

 

 

 

可以看到有5个类,其中:

  • ClassLoader是一个抽象类,其中定义了ClassLoader的主要功能。
  • SecureClassLoader继承了抽象类ClassLoader,但是SecureClassLoader并不是ClassLoader的实现类,而是拓展了ClassLoader类并且加入了权限方面的功能,加强了ClassLoader的安全性。
  • URLClassLoader继承SecureClassLoader,可以通过URL路径从jar文件和文件夹加载类和资源。
  • ExtClassLoader和AppClassLoader都是继承自URLClassLoader,它们都是Launcher的内部类,Launcher是Java虚拟机的入口应用,两者都是在Launcher中初始化的。

 

 

 

 

3.双亲委托模式:

类加载器查找Class采用的是双亲委托模式,所谓的双亲委托模式就是自定义类加载器首先从缓存中查找该class文件是否已经加载,如果没有,则不是自身去查找,而是委托给父加载器进行查找,这样依次递归,直到委托到最顶层的Bootstrap ClassLoader,如果Bootstrap ClassLoader找到了该class,就会直接返回,如果在缓存没有找到,则开始在目录寻找,如果没有找到,继续依次向下查找,如果还是没有找到则最后会交给自己目录去查找。

 

 

0984a467c0704cb2b167007f3b404cbe.png

 

 

3.1:总结:

  • 自定义类加载器首先从缓存中查找class文件是否已经加载,如果已经加载就返回,否则委托给父加载器,如果一直没有加载到,则一直委托到Bootstrap ClassLoader,如果Bootstrap ClassLoader在缓存都没有找到,那么则在它的目录查找,如果找到就返回class,没有就交给子加载器,子加载器重复该步骤查找目录,直到返回至自定义类加载器,如果还没有就抛出异常。
  • 采用双亲委托模式可以避免重复加载且更加安全。

 

 

 

4.自定义ClassLoader:

系统提供的类加载器只能够加载指定目录下的jar包和Class文件,如果想要加载网络上或者D盘某一个文件中的jar包和Class文件则需要自定义ClassLoader。实现自定义ClassLoader需要如下两个步骤:

  1. 定义一个自定义ClassLoader并且继承抽象类ClassLoader。
  2. 复写findClass方法,并且在findClass方法中调用defineClass方法。

 

 

 

 

 

Android中的ClassLoader:

Android中的ClassLoader和Java中的ClassLoader是有区别的。

 

 

1.ClassLoader的类型:

与Java中的ClassLoader加载的jar文件和class文件不同的是,Android中的DVM还是ART都是加载dex文件的。Android中的ClassLoader也分为两种类型,分别是系统类加载器和自定义类加载器。其中系统类加载器主要包括3种,分别是:BootClassLoader,Path ClassLoader和Dex ClassLoader。

 

 

 

1.1:BootClassLoader:

在Android系统启动时会使用BootClassLoader来预加载常用的类,与SDK中的BootstrapClassLoader不同的是,它并不是采用C/C++实现的,而是由Java实现的。BootClassLoader是ClassLoader的内部类,并且继承自ClassLoader,且它是一个单例类,而且只有在同一个包中才可以访问的,因此我们在应用程序中是无法调用的。

 

 

 

1.2:Dex ClassLoader:

Dex ClassLoader继承自BaseDexClassLoader,方法都在BaseDexClassLoader体现。Dex ClassLoader可以加载dex文件以及包含dex的压缩文件(例如:apk文件和jar文件),不管是加载哪一种文件,最终都是要加载dex文件的。Dex ClassLoader的构造方法有4个参数,分别是:

  • dexpath:dex相关文件路径的集合,多个路径使用文件分隔符分隔,默认是:。
  • optimizedDirectory:解压的dex文件的存储路径,必须是一个内部存储路径。
  • librarySearchPath:包含C/C++库的路径集合。
  • parent:父加载器。

 

 

 

1.3:Path ClassLoader:

Path ClassLoader继承自BaseDexClassLoader,方法都在BaseDexClassLoader体现。Android系统使用Path ClassLoader来加载系统类和应用程序的类,在Path ClassLoader中没有optimizedDirectory参数,这是因为Path ClassLoader已经默认了optimizedDirectory参数的值为:/data/dalvik-cache。所以Path ClassLoader无法定义解压的dex文件的存储路径,因此Path ClassLoader经常用来加载已经安装的apk的dex文件。

 

 

 

2.ClassLoader的继承关系:

在运行一个应用程序时需要用到两种类加载器,分别是:BootClassLoader和Path ClassLoader。其中Path ClassLoader的DexPathList中包含了很多的apk的路径,DexPathList就是在BaseDexClassLoader的构造方法中被创建的,里面存储了dex相关文件的路径,其中ClassLoader在执行双亲委托模式查找流程时会从DexPathList中进行查找。

 

41cbb4a268a845ea9764578c319a238e.png

 

 

图中一共有8个与ClassLoader相关的类,下面简单介绍一些类:

  • ClassLoader 是一个抽象类,其中定义了ClassLoader的主要功能。BootClassLoader是它的内部类。 
  • SecureClassLoader类和JDK8中的 SecureClassLoader类的代码是一样的,它维承了抽象类ClassLoader。 SecureClassLoader并不是ClassLoader的实现类,而是拓展了 方法,ClassLoader类加入了权限方面的功能,加强了ClassLoader的安全性。
  • URIClassLoader类和JDK 8中的URLClassLoader类的代码是一样的,它继承自SecureClassLoader,用来通过URL路径从jar文件和文件夹中加载类和资源。 
  • InMemoryDexClassLoader是Android 8.0 新增的类加载器,继承自BaseDexClassLoader,用于加载内存中的dex文件。
  • BaseDexClassLoader 继承自ClassLoader,是抽象类ClassLoader的具体实现类。PathClassLoader、DexClassLoader和 InMemoryDexClassLoader都继承自它。

 

 

 

3.ClassLoader的加载过程:

Android的ClassLoader同样采用了双亲委托模式,ClassLoader的加载方法为loadClass方法,这个方法被定义在抽象类ClassLoader中。ClassLoader的loadClass方法判断传入的类是否已经加载,如果没有就调用父加载器的loadClass方法,有就返回。同样如果委托过程没有找出来,就调用findClass方法进行查找流程。findClass方法需要由子类BaseDexClassLoader实现。在BaseDexClassLoader的构造方法中创建了DexPathList,并且后续调用了DexpathList的findClass方法。

DexpathList的findClass方法:通过遍历Element数组dexElement,然后调用Element的findClass方法,其方法内部会调用DexFile的loadClassBinaryName方法,DexFile的loadClassBinaryName方法中调用了defindClass方法,defindClass方法又调用了defineClassNative方法来执行查找流程,如果在Element(dex文件)找到了该类就返回,如果没有找到就接着在下一个Element进行查找。其中Element是DexPathList的静态内部类,内部封装了Dexfile,它用于加载dex。

 

 

 

4.BootClassLoader的创建:

BootClassLoader是什么时候被创建的呢?答案要从系统启动的Zygote进程启动开始说起,ZygoteInit的main方法通过preload方法预加载类和资源,preload方法中调用了ZygoteInit的preloadClasses方法,preloadClasses方法用于Zygote进程初始化时预加载常用类,该方法把PRELOADED_CLASSES的值是/system/etc/proloaded_classes文件封装为FileInputStream。该文件存有预加载类的目录。预加载是属于拿空间换时间的策略。接着把FileInputStream封装为BufferedReader,并且后续遍历BufferedReader,读出所有预加载类的名称,每读出一个就调用Class.forName方法加载该类。而在Class.forName方法中创建了BootClassLoader,它是用来加载该文件的预加载类的。

 

 

 

5.Path ClassLoader的创建:

Path ClassLoader的创建也是从Zygote进程开始说起,Zygote进程启动SystemServer进程时调用ZygoteInit的startSystemServer方法,快进到handleSystemServerProcess方法,该方法调用了createPathClassLoader方法创建了PathClassLoader。具体是createPathClassLoader方法中调用了PathClassLoaderFactory的createClassLoader方法利用工厂模式创建PathClassLoader。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值