2-类加载器

类加载机制

类加载器负责加载所有的类,一旦一个类被载入JVM中,同一个类就不会被再次载入了,那么,怎么才算“同一个类”。

正如一个对象有一个唯一标识,一个载入JVM的类也有一个唯一的标识。在Java中,用全限定类名作为标识;但在JVM中,一个类用全限定类名和类加载器作为唯一标识。例如,Person类的example包中,被类加载器ClassLoader的实例a所加载,它在JVM中表示为(Person, example, a)。这意味着两个类加载器加载的同名类也是不同的。

​ 当JVM启动时,会形成三个类加载器组成的初始类加载器层次结构:

  • BootStrap ClassLoader:根类加载器
  • Extension ClassLoader:拓展类加载器
  • System ClassLoader:系统类加载器

BootStrap ClassLoader被称为引导类加载器,负责加载Java的核心类。

JVM的类加载机制有三种:

  • 全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非是显式使用另外一个类加载器
  • 父类委托:是先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己类路径加载该类。
  • 缓存机制:缓存机制保证所有加载过的Class都会被缓存,当程序需要使用某个Class时,类加载器先从缓存区搜寻该Class,当缓存区没有,系统才会读取该类对应二进制文件,并转换为Class对象,存入缓存区。这是为什么修改Class后,必须重新启动JVM,修改才会生效的原因。

类加载器之间的父子关系不是类继承上的父子关系。这里的父子关系是指类加载器实例之间的关系。

根类加载器->拓展类加载器->系统类加载器->用户类加载器

JVM的根类加载器不是由Java实现的,而且程序一般不会访问根类加载器。

类加载器加载Class大概需要8个步骤:

  1. 检测此Class是否载入过,如果有,到第8步;没有执行第2步
  2. 如果父类加载器不存在(没有父类加载器,那么要么parent是根类加载器,要么自己本身就是根类加载器),执行第四步;如果父类加载器存在,到第3步
  3. 请求使用父类加载器载入目标类,成功载入,则到第8步;否则执行第5步
  4. 请求使用根类加载器载入目标类,成功载入,到第8步;否则执行第7步
  5. 当前类加载器尝试寻找Class文件(从与此ClassLoader相关的类路径寻找),如果找到执行第6步;找不到执行第7步
  6. 从文件中载入Class,成功载入后跳到第8步
  7. 抛出ClassNotFoundException异常
  8. 返回对应java.lang.Class对象

其中,第5、6步允许重写ClassLoader的findClass()方法来实现自己的载入策略,甚至重写loadClass实现自己的载入过程。

创建并使用自定义的类加载器

JVM中除了根类加载器之外的所有类加载器都是ClassLoader子类的实例。开发者可以拓展ClassLoader的子类,重写相应方法来实现自定义的类加载器。


2-类加载器
https://zhaoquaner.github.io/2022/05/11/Java/类加载机制和反射/2-类加载器/
更新于
2022年5月22日
许可协议