From 5b00338a68966969011d80124b6ff3ae5e2d7632 Mon Sep 17 00:00:00 2001 From: mumu Date: Sat, 11 Oct 2025 15:43:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E7=94=B1=E4=BA=8E=20JDK=2024+=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=8C=E4=BC=98=E5=8C=96=20ServiceLoader?= =?UTF-8?q?=20=E5=8A=A0=E8=BD=BD=E7=AC=AC=E4=B8=80=E4=B8=AA=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E6=9C=8D=E5=8A=A1=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为兼容 JDK 24 及以上版本中ServiceLoader#iterator 可能抛出 NoClassDefFoundError 的情况,优化 loadFirstAvailable 方法,统一在 hasNext 与 next 调用时安全忽略异常,确保能正确返回首个可用的非空实例。 Closes https://gitee.com/chinabugotech/hutool/issues/ID0952 --- .../hutool/core/util/ServiceLoaderUtil.java | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java index d04807d5f..69666f061 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java @@ -2,10 +2,7 @@ package cn.hutool.core.util; import cn.hutool.core.collection.ListUtil; -import java.util.Iterator; -import java.util.List; -import java.util.ServiceConfigurationError; -import java.util.ServiceLoader; +import java.util.*; /** * SPI机制中的服务加载工具类,流程如下 @@ -23,19 +20,36 @@ import java.util.ServiceLoader; public class ServiceLoaderUtil { /** - * 。加载第一个可用服务,如果用户定义了多个接口实现类,只获取第一个不报错的服务 + * 加载第一个可用的 Service 实现。 + *

+ * 为兼容 JDK 24+ 中 {@link ServiceLoader} 在加载服务实现时可能抛出的 {@link NoClassDefFoundError}, + * 此方法在调用 {@code hasNext()} 和 {@code next()} 时安全忽略异常。 + * 当遇到依赖缺失或配置错误的实现时会自动跳过,并返回第一个可用的非空实例。 + *

* - * @param 接口类型 - * @param clazz 服务接口 - * @return 第一个服务接口实现对象,无实现返回{@code null} + * @param clazz 服务接口类型 + * @param 服务实现类型 + * @return 第一个可用的非空实现,若无可用实现则返回 {@code null} + * @since 5.8.41 (JDK 24+ 兼容优化) + * @see JDK-8350481 */ public static T loadFirstAvailable(Class clazz) { - final Iterator iterator = load(clazz).iterator(); - while (iterator.hasNext()) { + final ServiceLoader loader = ServiceLoader.load(clazz); + final Iterator iterator = loader.iterator(); + while (true) { + T instance; try { - return iterator.next(); - } catch (ServiceConfigurationError ignore) { - // ignore + // 注意:JDK 24+ 下 hasNext() 和 next() 均可能触发 NoClassDefFoundError + if (!iterator.hasNext()) { + break; + } + instance = iterator.next(); + } catch (ServiceConfigurationError | NoClassDefFoundError e) { + // 安全忽略当前实现,尝试下一个 + continue; + } + if (instance != null) { + return instance; } } return null;