JVM之类加载与双亲委派


系统加载Class类型的文件主要三步:加载->连接->初始化。连接又可以分为三步:*验证->准备->解析

类加载过程描述

类加载过程完成的事情

  1. 通过全类名获取定义此类的二进制字节流
  2. 将字节流所代表的静态存储结构转为方法区的运行时数据结构
  3. 在内存中生成一个代表该类的Class对象,作为方法区这些数据的访问入口

类加载器

java中内置了三个重要的ClassLoader

  1. BootstrapClassLoader(启动类加载器):最顶层的加载类,负责加载%JAVA_HOME%/lib目录下的 jar 包和类;
  2. ExtensionClassLoader(扩展类加载器):主要负责加载目录%JRE_HOME%/lib/ext 目录下的 jar 包和类;
  3. AppClassLoader(应用程序类加载器):面向用户的加载器,负责加载当前应用calsspath下所有的jar包和类

双亲委派模型

介绍

每一个类都有一个对应的类加载器。系统中的类加载器在协同工作的时候会默认使用双亲委派模型。即在类加载的时候,系统会首先判断当前类是否被加载过,以及被加载的类会直接返回,否则才会尝试加载。加载的时候首先会把该请求委派该父类加载器的loadClass()处理,因此所有的请求最终都会传送到顶层启动类加载器BootstrapClassLoader中。当父类加载器无法处理,才会由自己处理。当父类加载器为null,会使用BootstrapClassLoader作为父类加载器。

当一个类加载器收到了类加载的请求的时候,他不会直接去加载指定的类,而是把这个请求委托给自己的父加载器去加载。只有父加载器无法加载这个类的时候,才会由当前这个加载器来负责类的加载

实现

  1. 先检查类是否已经被加载过
  2. 若没有加载则调用父加载器的loadClass()方法进行加载
  3. 若父加载器为空则默认使用启动类加载器作为父加载器。
  4. 如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。

双亲委派模型的优点

  • 避免类的重复加载
  • 避免核心类被不同类加载器加载产生冲突,保证核心库的安全

如何打破双亲委派模型

不仅要继承ClassLoader类,还要重写loadClass和findClass方法。如果不想打破,重写ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。

loadClass() 就是主要进行类加载的方法,默认的双亲委派机制就实现在这个方法中。
findClass() 根据名称或位置加载.class字节码




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score