【JVM】ClassLoader

类加载器

从我的上一篇JVM体系结构文章的中可以看出,在 JVM 的内存模型中,类加载器是处于一个较为重要的位置。

类加载器负责将 Java 的 .class 文件加载入 JVM 的内存区域,.class 文件的开头都有特定的文件标识,并且将这些内容转换成方法区中的运行时数据结构,类加载器只负责加载 .class 文件,Execution Engine 决定其是否能运行。

下图是类加载器将 .class 文件加载到 JVM 的过程:

类加载器将 .class 文件加载后,会初始化一个类模板,该类的所有实例都会通过这个类模板创建出来。

类加载器种类

类加载器当然不止一种,从大体上,类加载器可以分为4种。

Java 虚拟机中自带的类加载器有:

  1. 启动类加载器(Bootstrap):通过C++实现的
  2. 扩展类加载器(Extension):通过Java实现的
  3. 应用程序加载器(AppClassLoader):也称为系统类加载器

用户自定义的类加载器:

  1. Java.lang.ClassLoader 的子类,用户可以自定义类的加载方式

下图为各个类加载器的层级关系图:

我们用代码来测试一下,通过 Java 原生 Object 类和自定义的 App 类,查看他们的类加载器和类加载器的层级关系。

可以看出,启动类加载器在打印的时候是 null,这是因为启动类加载器是通过 C++ 语言实现的,Java 没办法直接操作。自定义的 App 类就是应用程序加载器。

双亲委派模型

在类加载器中还需要提及的就是类加载器的双亲委派模型

当一个类需要加载的时候,首先他不会自己去加载这个类,而是把这个类加载的请求委派给父类的类加载器加载,每一层类加载器都是这样,直到委派给启动类加载器,只有最顶层的类加载器无法加载这个类请求时,子类的类加载器才会开始尝试加载。

优点

使用双亲委派模型可以防止污染 Java 源代码,比如我们自定义了一个 string 类,但是 java 源代码中已经有了 string,由于我们自己自定义的 string 类加载器属于应用程序加载器,根据双亲委派模型,会先让启动类加载器加载,所以会加载 jdk 中的 string 类,保证了使用不同的类加载器最终得到的是同一个对象。


我们做一个小小的测试,新建一个类叫做String,与JDK包中的String同名,实例化这个String类,看看会发生什么??

这里我在String类的空构造上打印了一句话,想看看在创建String对象的时候会不会调用到。

打印出来的结果是报错,也就证明了Java检测到我们自定义的String类和JDK中的String类同名,启动类加载器加载时抛出错误。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章