You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级至Java17+Tomcat10+SpringBoot3后ForkJoinPool加载类路径资源失败

问题解决:Tomcat 10中ForkJoinPool线程加载类路径资源失败

核心原因

Tomcat 10(基于Jakarta EE 9+)的类加载机制与Tomcat 8存在差异,且ForkJoinPool的工作线程默认使用系统类加载器,而非Web应用专属的类加载器。普通Thread/ExecutorService的线程会继承父线程(Web请求线程)的上下文类加载器(对应WEB-INF/classes的类加载器),但ForkJoinPool的线程池是提前初始化的,无法自动继承Web应用的类加载上下文,导致找不到classpath下的资源。

解决方案

1. 显式设置ForkJoinPool任务的上下文类加载器

在提交到ForkJoinPool的任务中,手动将线程的上下文类加载器设置为当前Web应用的类加载器,再执行资源加载逻辑:

// 在Web请求线程中获取当前应用的类加载器
ClassLoader appClassLoader = Thread.currentThread().getContextClassLoader();

ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(() -> {
    // 强制设置上下文类加载器为Web应用类加载器
    Thread.currentThread().setContextClassLoader(appClassLoader);
    
    // 加载字体文件示例
    try (InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("fonts/your-font.ttf")) {
        // 资源处理逻辑
    } catch (IOException e) {
        e.printStackTrace();
    }
}).join();

2. 使用Spring Boot的ResourceLoader加载资源(推荐)

Spring Boot 3的ResourceLoader会自动绑定Web应用的类加载器,无需手动处理上下文,兼容性更强:

// 注入Spring的ResourceLoader
@Autowired
private ResourceLoader resourceLoader;

// 在ForkJoinPool任务中加载资源
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(() -> {
    try {
        Resource fontResource = resourceLoader.getResource("classpath:fonts/your-font.ttf");
        try (InputStream fontStream = fontResource.getInputStream()) {
            // 资源处理逻辑
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}).join();

3. 验证资源路径与打包结果

  • 解压WAR包确认fonts目录确实存在于WEB-INF/classes下
  • 资源路径使用classpath:fonts/xxx.ttf格式,避免开头加斜杠(如/fonts/xxx.ttf会导致路径解析错误)

内容的提问来源于stack exchange,提问作者Raffa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:43:20