Skip to the content.

首页

类加载


类的生命周期

加载 -> 连接(验证 -> 准备 -> 解析)-> 初始化 -> 使用 -> 卸载


类加载机制

类型的加载、连接和初始化过程都是在Java程序运行期间完成的,会给提起编译带来困难,也会增加性能开销,而动态加载动态连接保证了Java语言可动态拓展的能力。


类加载的时机

有且只有六种主动引用的情况必须对类进行初始化(类加载自然要在初始化之前开始):

被动引用不会触发初始化:


类加载的过程

加载

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

连接

加载阶段与连接阶段的部分动作是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,确定的是连接阶段的开始固定晚于加载阶段的开始时间

初始化

类加载过程的最后一步,执行类构造器<clinit>方法,只有主动引用才会触发类的初始化


类加载器

负责“通过一个类的全限定名获取定义此类的二进制字节流”这一动作;每一个类加载器都有独立的类名称空间,任意一个类都必须由加载它的类加载器和这个类本身才能确定其在Java虚拟机中的唯一性

双亲委派模型

从虚拟机的角度只存在启动类加载器(C++语言实现,属于虚拟机的一部分)和其他类加载器(Java语言实现,继承自java.lang.ClassLoader)。双亲委派模型要求除了启动类加载器,其余的类加载器都应有自己的父类加载器。

双亲委派模型的工作过程

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载,而是把请求委派给父类加载器去完成,每一个层次的类加载器都是如此,只有当父类加载器无法完成加载请求时,子加载器才会尝试自己去完成加载。它是用来保证Java程序运行所需要的核心类被篡改和重复加载,JDK1.2中引入,在ClassLoader类的loadClass()方法中实现

破坏双亲委派模型

  1. JDK1.2时才引入,为了向前兼容,loadClass方法修饰符为protected,且增加了一个新的protected方法findClass交由用户去重写;
  2. Java中SPI的加载,如JNDI、JDBC等,ServiceLoader使用线程上下文类加载器来加载用户的具体实现;
  3. Java模块化、热部署技术。

模块化

jdk.internal.loader.BuiltinClassLoader实现了JDK9中模块化架构下的类加载的逻辑,作为新增加的BootClassLoader、PlatformClassLoader、AppClassLoader的父类;三个类加载器各自负责加载不同的模块,平台及应用程序类加载器收到类加载请求后,会优先委派给该类归属模块的类加载器完成加载