# Tomcat WebappClassLoader 类加载机制源码分析

JVM类加载机制参考：[JAVA程序运行原理分析](/performance-optimization/jvmyou-hua-pian/javacheng-xu-yun-xing-yuan-li-fen-xi.md)

## tomcat中的ClassLoader <a href="#tomcat-zhong-de-classloader" id="tomcat-zhong-de-classloader"></a>

![](/files/-Ltdv9hPr3QXCH2XgZOx)

* 启动类加载器（BootStrap ClassLoader）：引导类装入器是用本地代码实现的类装入器，它负责将 jdk中jre/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节，开发者无法直接获取到启动类加载器的引用，所以不允许直接通过引用进行操作。
* 扩展类加载器（Extension ClassLoader）：扩展类加载器是由Sun的ExtClassLoader（sun.misc.Launcher$ExtClassLoader）实现的。它负责将jdk中jre/lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
* 系统类加载器（System ClassLoader）：系统类加载器是由 Sun的 AppClassLoader（sun.misc.Launcher$AppClassLoader）实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。
* StandardClassLoader 负责加载tomcat容器相关的类
* WebappClassLoader 是每个web项目对应一个WebappClassLoader。这样做的目的是每个项目中都会有相同的类（package+classname），而类的内容不一样。这样每个项目一个WebappClassLoader可以达到隔绝项目类冲突的问题。

## WebappClassLoader的类加载机制

## 第一步 <a href="#di-yi-bu" id="di-yi-bu"></a>

![](/files/-Ltdv9hRqPj5n0Zjdos_)

首先调用findLoaderClass0() 方法检查WebappClassLoader中是否加载过此类。

![](/files/-Ltdv9hTCtV7ibjSE9lJ)

WebappClassLoader 加载过的类都存放在 resourceEntries 缓存中。

```
protected final Map<String, ResourceEntry> resourceEntries =  new ConcurrentHashMap<>();
```

## 第二步 <a href="#di-er-bu" id="di-er-bu"></a>

![](/files/-Ltdv9hV8alcVyRWgYDS)

如果第一步没有找到，则继续检查JVM虚拟机中是否加载过该类。

调用ClassLoader的findLoadedClass() 方法检查

## ![](/files/-Ltdv9hXYuZy5oLzsCUm)

## 第三步

![](/files/-Ltdv9hZ0P4cmZHO6rhS)

如果前两步都没有找到，则使用AppClassloader加载该类（也就是当前JVM的ClassPath）

## 第四步 <a href="#di-si-bu" id="di-si-bu"></a>

![](/files/-Ltdv9ha2rvyE3upUw1-)

如果前三步都没找到，通过filter() 方法检查该类是否在定义的包名下，如果在则通过 StandardClassLoader类加载。

![](/files/-Ltdv9hcQtgrZQMjLbb3)![](/files/-Ltdv9he2HClJDClnnlB)

## ![](/files/-Ltdv9hg9YiVTfbd4wqV)

## 第五步

![](/files/-Ltdv9hiNMKAshWaVYYu)

如果前4步都没有找到，将由WebappClassLoader来加载。

## ![](/files/-Ltdv9hk6WL-G3gqkaHA)

从当前的工程的Web-INF/classes 目录下查找

![](/files/-Ltdv9hmCWu3eMxE8AvG)如果找到，则创建ResourceEntry对象，保存这个类的元信息，并把他保存在WebappClassLoader的resourceEntries中，便于下次查找。

**本人简书blog地址：**[**http://www.jianshu.com/u/1f0067e24ff8**](http://www.jianshu.com/u/1f0067e24ff8)\
[**点击这里快速进入简书**](http://www.jianshu.com/u/1f0067e24ff8)

**GIT地址：**[**http://git.oschina.net/brucekankan/**](http://git.oschina.net/brucekankan/)\
[**点击这里快速进入GIT**](http://git.oschina.net/brucekankan/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tuonioooo-notebook.gitbook.io/performance-optimization/jvmyou-hua-pian/tomcat-webappclassloader-lei-jia-zai-ji-zhi-yuan-ma-fen-xi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
