This website requires JavaScript.

什么是ClassLoader

1 2020-07-11 20:40:24 12

什么是ClassLoader

ClassLoader在Java中有非常重要的作用,它主要工作在Class装载的加载阶段,其主要的作用是从系统外部获得Class二进制数据流。

它是Java的核心组件,所有的class都是由ClassLoader进行加载的,ClassLoader负责将Class文件里的二进制数据装载进系统,然后交给Java虚拟机进行连接,初始化等操作。

ClassLoader种类

名称 作用
启动类加载器(Bootstrap ClassLoader) C++编写,在java里无法获取,负责加载/lib(Java.*)下的类。
扩展类加载器(Extension ClassLoader) Java编写,可以在java里获取,负责加载/lib/ext下的类。
系统类加载器/应用程序类加载器(Application ClassLoader) 是与我们接触对多的类加载器,我们写的代码默认就是由它来加载,ClassLoader.getSystemClassLoader返回的就是它。
自定义ClassLoader Java编写,定制化加载

ClassLoader的双亲委派机制

Java中任意一个类,都需要由加载它的类加载器和这个类本身来一同确立其在Java虚拟机中的唯一性,判断一个类是否相同,通常用equals()方法,isInstance()方法和isAssignableFrom()方法。来判断,对于同一个类,如果没有采用相同的类加载器来加载,在调用的时候,会产生意想不到的结果;

如果不是同一个类加载器加载,即时是相同的class文件,也会出现判断不想同的情况,从而引发一些意想不到的情况,为了保证相同的class文件,在使用的时候,是相同的对象,jvm设计的时候,采用了双亲委派的方式来加载类,同时也避免多份同样字节码的加载:类似于单例模式,多个ClassLoader只需要加载一个类字节码即可。形成一个整体的一种机制。

如图所示,自下而上查找某个类是否被加载过,首先从CustomClassLoader开始查找(findClass)如果有加载过直接返回,如果没加载过就会委派给AppClassLoader去查找,依次查询。 image

类的装载过程

image

双亲委派代码解析

一起看下在java.lang.ClassLoader中的loadClass方法,由递归实现

大体流程:

  1. 子类先委托父类加载
  2. 父类加载器有自己的加载范围,范围内没有找到,则不加载,并返回给子类
  3. 子类在收到父类无法加载的时候,才会自己去加载
        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
// 使用指定的<a href="#name">二进制名称</a>加载类,默认实现按以下顺序搜索类 // 1. 调用findLoadedClass()检查类是否已经加载 // 2. 调用父类加载器方法的loadClass。 如果父级为null,则该类使用内置虚拟机的加载程序。 // 3. 调用父类加载器没找到则自己调用findClass(String)方法来找到类 // 如果使用上述步骤找到了该类,并且resolve标志为true,然后此方法将调用生成的Class 对象上的#resolveClass(Class)}方法。 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded (首先先查看这个类是不是已经加载过) Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order to find the class.(如果还是没有获得该类,调用findClass找到类) long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats (记录JVM数据) sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } // 链接到指定的类,初始化等 if (resolve) { resolveClass(c); } return c; } }

破坏双亲委派

待续...

免责声明

本站提供Hack区的一切软件、教程和仅限用于学习和研究目的;不得将其用于商业或者非法用途,否则,一切后果由用户自己承担 您必须在下载后的24个小时之内, 从您的电脑中彻底删除。如果条件支持,请支持正版,得到更好的服务。 另如有侵权请邮件与我 联系处理。敬请谅解!

本文于   2020/7/11 下午  发布 

永久地址: https://madaoo.com/article/1281931346926768128

版权声明: 自由转载-署名-非商业性使用   |   Creative Commons BY-NC 3.0 CN