Skip to content

ClassLoader在dev环境无法加载到配置文件问题

问题排查过程

背景

一模块使用第三方提供的sdk, 在本地运行ok, 与关联方联调成功, 但部署到dev后无法调通

排查过程

  1. 排查整个联调链路, 网络无问题, 关联方无问题, 问题定位到请求方, 即我方模块

  2. 由于本地代码没有问题, 本地运行的是编译后的代码, dev运行的是部署后的代码, 两者最大的差距可能就是打包后的配置问题

  • 本地打jar包运行, 排查是否是容器环境问题, 结果是本地打的jar包依旧请求不到关联方
  • 排查打包后相关配置文件的加载, 确认到sdkjar包中的配置信息加载不到, sdk有问题
  • 1744290015240
  • 定位到问题源码
  • 1744290209212

解决方案

  • 改用Thread.currentThread().getContextClassLoader()
  • 改CfgUtil类, 然后编译成class文件, 替换sdk的这个文件, 然后重新打包(这里直接打zip改成jar后缀就行)上传私服即可

原理解析

类加载器父加载器负责加载的类路径用途与特点
BootstrapClassLoadernull(最顶层)JVM 核心类库:``- $JAVA_HOME/jre/lib- -Xbootclasspath 指定的路径由 C++ 实现,加载 Java 核心类(如 java.lang.*),无法直接操作。
ExtClassLoaderBootstrapClassLoader扩展类路径:``- $JAVA_HOME/jre/lib/ext- -Djava.ext.dirs 指定的目录加载 Java 扩展库(如 javax.servlet),增强核心功能。
AppClassLoaderExtClassLoader应用类路径:- `-classpath` 或 `-cp` 指定的路径- 默认当前目录 (.)加载用户代码和第三方依赖,是默认的类加载器(通过 ClassLoader.getSystemClassLoader() 获取)。
LaunchedURLClassLoaderAppClassLoader(可配置)Spring Boot 应用类路径 + 依赖 JAR 包:``- 打包后的 BOOT-INF/classes- BOOT-INF/lib/*.jarSpring Boot 特有,支持模块化加载和热部署,通过 spring-boot-loader 实现。
  • ClassLoader.getSystemResourceAsStream()使用的是 AppClassLoader
  • 本地ok, 是因为 AppClassLoader, 在IDEA环境时可以加载到target目录下的所有文件
  • dev不行, 是因为 AppClassLoader无法加载到 springboot-fat.jar下应用 jar中的配置文件, 应该使用 Thread.currentThread().getContextClassLoader()以切换成 LaunchedURLClassLoader加载