如何处理Spring Boot类加载器与ForkJoin池相关异常问题?
关于Spring Boot + ForkJoinPool类加载器兼容性问题的疑问
背景信息
Java 9中为修复JDK-8172726 bug,修改了ForkJoin common pools的类加载器处理逻辑,由此引发了一系列兼容性问题。Spring Boot仓库中多个相关issue被关闭,理由为该问题属于JDK修复导致的结果,并非Spring自身问题。
触发场景限制
- 仅在通过
java -jar build/libs/my-application-0.0.1-SNAPSHOT.jar运行Spring Boot应用时出现问题,此时应用启用了Jar包自带的Spring Boot类加载器,改变了类路径中类文件与Jar包的顺序 - 使用
gradle bootRun、IDE运行,或者将Jar包解压后通过java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication运行(此时使用AppClassLoader而非Spring Boot类加载器)时,问题不会出现
问题现象
使用ForkJoin池(如Stream.parallel().forEach(...))时,发起调用的线程使用Spring Boot类加载器,但工作线程使用AppClassLoader,这种类加载器不一致的情况会偶尔导致工作线程无法加载Spring Boot类加载器可识别的类。
已编写小型Spring Boot示例项目复现该问题,核心代码如下:
IntStream.range(0, 500).parallel().forEach(i -> { try { // 工作线程执行时抛出 java.lang.ClassNotFoundException: org.glassfish.jaxb.runtime.v2.ContextFactory JAXBContext.newInstance(ObjectFactory.class); } catch (Exception e) { try { // 工作线程执行时成功加载类 Class.forName("org.glassfish.jaxb.runtime.v2.ContextFactory"); } catch (ClassNotFoundException ex) { // 异常处理逻辑 } } });
出现矛盾现象:工作线程中调用JAXBContext.newInstance(ObjectFactory.class)抛出类未找到异常,但调用Class.forName("org.glassfish.jaxb.runtime.v2.ContextFactory")却能成功加载该类。
核心疑问
- 工作线程触发该类加载异常的具体条件是什么?目前仅发现JAXBContext实例化、Java ServiceLoader无法找到已注册服务的场景会触发问题。
- 为何同一工作线程中,
JAXBContext.newInstance无法加载目标类,但Class.forName却能成功? - 如何正确处理该兼容性问题?需明确在通过
java -jar运行Spring Boot应用(使用Spring Boot类加载器)时,使用Stream.parallel()或标准ForkJoinPool的正确方案。
内容的提问来源于stack exchange,提问作者fnumrich
相关产品推荐
相关产品推荐

