Skip to content

fix(archive): 修复 JarUtils.parseArtifactId 不支持解析 .jar-unpack 目录路径 (合并到 3.1.x)#1113

Open
LuotuoMianyang wants to merge 1 commit into
sofastack:3.1.xfrom
LuotuoMianyang:fix/jar-utils-unpack-3.1.x
Open

fix(archive): 修复 JarUtils.parseArtifactId 不支持解析 .jar-unpack 目录路径 (合并到 3.1.x)#1113
LuotuoMianyang wants to merge 1 commit into
sofastack:3.1.xfrom
LuotuoMianyang:fix/jar-utils-unpack-3.1.x

Conversation

@LuotuoMianyang

@LuotuoMianyang LuotuoMianyang commented May 28, 2026

Copy link
Copy Markdown
Contributor

概要

#1105 回合到 3.1.x 分支。

在 unpack 模式下,ExplodedBizArchive 会将解压目录添加到类路径 URL 列表中。JarUtils.parseArtifactId 无法处理以 .jar-unpack 结尾的路径,导致启用 declareMode=true 时解析失败。

改动内容

  • JarUtils.parseArtifactId() 中增加对 .jar-unpack 路径的检测
  • 新增 parseArtifactIdFromUnpackedDir() 方法,从解压目录中的 pom.properties 提取 artifactId
  • pom.properties 不存在时,回退到从目录名解析

测试覆盖(9 个测试用例)

  • 标准 META-INF/maven-archiver 位置
  • 非标准嵌套目录位置
  • 目录不存在的情况
  • pom.properties 中 artifactId 为空
  • 缺少 artifactId 属性
  • 完全没有 pom.properties
  • 回退到文件名解析(有版本号/无版本号)
  • 基于资源 URL 的解析

测试结果

  • sofa-ark-archive 模块全部 22 个测试通过
  • JarUtilsTest — 原有测试正常通过
  • JarUtilsParseArtifactIdFromUnpackedDirTest — 9 个新测试用例全部通过

In unpack mode, ExplodedBizArchive adds the unpacked directory to classpath
URLs. JarUtils.parseArtifactId failed to handle paths ending with .jar-unpack,
causing issues when declareMode is enabled. Add detection for .jar-unpack paths
with fallback to directory name parsing.

Cherry-picked from PR sofastack#1105 (master) to 3.1.x branch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sofastack-cla sofastack-cla Bot added bug Something isn't working cla:yes size/L labels May 28, 2026
@codecov

codecov Bot commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (1f19e51) to head (9e7d223).

Files with missing lines Patch % Lines
.../java/com/alipay/sofa/ark/loader/jar/JarUtils.java 0.00% 20 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##           3.1.x   #1113   +/-   ##
=====================================
  Coverage   0.00%   0.00%           
=====================================
  Files        167     167           
  Lines       6986    7006   +20     
  Branches    1029    1035    +6     
=====================================
- Misses      6986    7006   +20     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xymak xymak requested a review from lvjing2 June 15, 2026 03:16
@DaviiidLi

DaviiidLi commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

@LuotuoMianyang 感谢这个修复,unpack 模式下 parseArtifactId 崩溃的问题确实存在,整体方向和测试覆盖都很好。

有一个性能问题建议修复:

unpack 分支绕过了 artifactIdCacheMap 缓存

当前把 unpack 判断放在了 computeIfAbsent 之前直接 return,导致同一个 unpack 路径每次调用都会走 parseArtifactIdFromUnpackedDirsearchPomProperties 递归遍历目录树。而
parseArtifactId 是类加载的热点路径(BizModel.doCheckDeclaredAbstractClasspathClassLoader.uniqueUrls 频繁调用),大 biz 解压后文件较多时会有性能开销。

建议把 unpack 逻辑移到缓存 lambda 内部,和其他路径保持一致:

public static String parseArtifactId(String jarLocation) {
    // 移除顶部的 unpack early-return

    // 截断 .jar 时排除 .jar-unpack
-   if (jarLocation.contains(JAR_SUFFIX)) {
+   if (jarLocation.contains(JAR_SUFFIX) && !jarLocation.contains(JAR_UNPACK)) {
        jarLocation = jarLocation.substring(0, jarLocation.lastIndexOf(JAR_SUFFIX) + JAR_SUFFIX.length());
    }
    // ... file: prefix stripping, ModifyPathUtils ...

    String finalJarLocation = jarLocation;
    artifactIdCacheMap.computeIfAbsent(jarLocation, a -> {
        try {
            String artifactId;
+           if (a.contains(JAR_UNPACK)) {
+               // unpack 模式:从解压目录的 pom.properties 或目录名解析
+               artifactId = parseArtifactIdFromUnpackedDir(a);
+               if (StringUtils.isEmpty(artifactId)) {
+                   artifactId = doGetArtifactIdFromFileName(a);
+               }
+           } else {
                String[] as = a.split(JAR_SEPARATOR, -1);
                // ... 原有逻辑不变 ...
+           }
            return Optional.ofNullable(artifactId);
        } catch (IOException e) {
            throw new RuntimeException(String.format(
                "Failed to parse artifact id from jar %s.", finalJarLocation), e);
        }
    });
    return artifactIdCacheMap.get(jarLocation).orElse(null);
}

这样 unpack 路径也能命中缓存,同一个路径只解析一次。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cla:yes size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants