大纲

1、ClassLoader
1.1、ClassLoader的作用
1.2、ClassLoade的规范 (双亲委任模型)
1.3、自定义ClassLoader
2、Tomcat ClassLoader
2.1、Tomcat ClassLoader 模型
2.2、Tomcat 加载顺序
2.3、SystemClassloader和AppClassLoader有什么区别
3、SpringBoot的n种启动方式以及ClassLoader的作用
4、Arthas/Skywalking是如何使用的

ClassLoader

ClassLoader的作用

作用: 将.class文件从磁盘(网络)中加载的文件转换为class内存实例

双亲委任模型

image.png

SPI 是如何打破双亲委任模型的

自定义ClassLoader

  1. @Test
  2. public void loadClass() throws ClassNotFoundException {
  3. String agentPath = "/Users/chenshun/open/classloader-dmeo/src/test/resources/lib";
  4. File dir = new File(agentPath + "/lib");
  5. File[] files = dir.listFiles();
  6. assert files != null;
  7. URL[] urls = new URL[files.length];
  8. for (int i = 0; i < files.length; i++) {
  9. urls[i] = toUrl(files[i]);
  10. }
  11. CustomClassLoader customClassLoader = new CustomClassLoader(urls, Object.class.getClassLoader());
  12. final Class<?> aClass = customClassLoader.loadClass("org.apache.log4j.Level", false);
  13. System.out.println(aClass.getName());
  14. }

Tomcat ClassLoader

经典的ClassLoader应用

模型

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/191132/1627637613130-4389c479-c52d-4329-a917-89244cfa032e.png#align=left&display=inline&height=525&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1050&originWidth=640&size=222892&status=done&style=none&width=320) ![image.png](https://cdn.nlark.com/yuque/0/2021/png/191132/1627638132786-f7fea7ce-61c9-411f-ac38-8d178002b2be.png#align=left&display=inline&height=480&margin=%5Bobject%20Object%5D&name=image.png&originHeight=960&originWidth=890&size=83104&status=done&style=none&width=445)

加载顺序

1、检查Tomcat是否是正常运行,停止的Tomcat会抛出异常。异常日志如下
2、从本地缓存中加载Class (Tomcat 自身加载级别)
3、检查我们之前加载的类缓存 (Parent 加载级别)
4、使用System Classloader 开始进行加载(SystemClassLoader==AppClassLoader)
4.1、优先使用System进行加载,防止Class覆盖,例如我写了一个java.lang.String.
5、是否委托给Parent ClassLoader加载,默认为false
6、搜索本地的repo
6.1、检查Tomcat运行状态
6.2、优先查找Tomcat下的资源
6.2.1、检查Tomcat运行状态
6.2.2、查找com/example/AppInfo,进入WebResourceRoot进行查找
6.2.2.1、优先查找 WEB-INF/classes
6.2.2.2、随后是 WEB-INF/lib
6.2.2.3、对 JAR 文件的搜索顺序将在对该方法的后续调用中保持一致,直到重新加载 Web 应用程序。不保证 JAR 文件的搜索顺序可能是什么。
6.2.2.4、查找资源StandardRoot#getResourceInternal
6.2.2.4.1、StandardRoot#processWebInfLib(); 加载lib文件
6.3、委托给父类URLClassLoader进行查找
6.4、都没有找到. 抛出ClassNotFoundException
7、如果6没有找到,委托给Parent查找
8、还是没有找到,抛出ClassNotFoundException

SystemClassloader和AppClassLoader有什么区别

没区别

SpringBoot是如何使用ClassLoader的

SpringBoot项目比较常见的问题我本地IDEA跑的好好的,为什么部署到线上就不行了呢。 这里就是Classloader在作怪

Arthas/Skywalking 等APM是如何使用ClassLoader的

其他

SPI

The public ServiceLoader API is available in Java SE 6. Although the loader service existed as early as JDK 1.3, the API was private and only available to internal Java runtime code.