沉舟侧畔千帆过,病树前头万木春
一文读懂Java的Classloader机制
2019-07-25 / 3 min read

Java Classloader是怎样定义的

从wikipedia上我们可以找到Java Classloader的定义:

The Java Class Loader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine.

这个定义从用途角度出发明确了Java Classloader的核心职责:将Java class动态加载到JVM中。
从概念上看,classloader和JVM以及JRE的关系如下图
classloader和JVM的关系
从功能视角来看,classloader提供了一种能力,把操作系统里的文件和文件格式差异抹平,以统一的class格式提供给JVM。如下图:
classloader的功能视角

classloader的分类

JDK为我们提供了多种classloader, 从上到下依次是:

  1. Bootstrap Classloader, 这个是根加载器,加载java_home/lib下的类库,JDK专用,开发者无法直接获取和使用。
  2. Extension Classloader是扩展类加载器,负责加载java_home/lib/ext路径下的类和系统变量java.ext.dir定义路径下的类。这个有了一定的自由度,并且支持开发者直接访问和使用。
  3. App Classloader是应用类加载器(又称系统类加载器),负责加载classpath下的类库,开发者可以直接使用。
    除此之外还可以自定义自己的类加载器 。这些类加载器的层级结构如下图:
    classloader的层级关系

classloader的工作过程

classloader的工作过程大致是这样的:

  1. 找到要加载的类 findClass
  2. 对要加载的类进行增删改
  3. 加载类 loadClass
    我们在实现自己的classloader的过程中一般也就是根据需要实现相关的操作。

双亲委派机制

多个classloader在加载类的过程中,难免会遇到冲突问题:同样路径和名字的类,到底由谁来加载呢?

JDK提供的解决方案是“双亲委派”,以确定classloader的优先级。
具体策略是在子classloader中发现某个类并不着急加载它,而是委托给它的parent,parent classloader也不着急加载,也是优先去自己的parent classloader询问。如此递归一直找到Bootstrap Classloader, 如果路径中都找不到,那么最末端的子classloader加载,否则就是最上游的类加载器加载。

这个模型的设定是:你写的不如官方的靠谱,核心功能不要随便改写,否则后果不可预料。初衷无疑是为了安全和可靠。

现实世界的classloader

现实世界中有很多类型的classloader,下面介绍两个在项目开发中常见的两个:

Spring和Sring mvc的classloader

Spring boot devtools的classcloader

什么时候你需要定义自己的classloader