Repository navigation
fix: 修复 Linux arm64 上压缩包无法预览 - #804
Open
yuhaibohotmail wants to merge 1 commit into
Open
yuhaibohotmail wants to merge 1 commit into
yuhaibohotmail wants to merge 1 commit into
Conversation
在 aarch64 的 Linux 上预览 zip/rar/7z 等压缩包时提示「该压缩包文件无法处理!」,
日志为 SevenZipNativeInitializationException: Can't find suited platform for
os.arch=aarch64, os.name=Linux。
原因有两处:
1. sevenzipjbinding-all-platforms 16.02-2.01 只包含 Linux-amd64、Linux-i386、
Mac-x86_64、Windows-amd64、Windows-x86 的原生库,没有 Linux arm64。
2. SevenZipJBinding 自动选择平台时用 os.name 的第一个单词 + "-" + os.arch
拼出 Linux-aarch64,而 arm64 原生库所在的目录是 Linux-arm64,只引入
原生库仍然匹配不到。
修改:
- 引入同版本的 sevenzipjbinding-linux-arm64,放在 all-platforms 之后
(两个 jar 各带一份同名的平台列表文件,SevenZipJBinding 只读取类路径上的
第一份,顺序反过来其它平台也会去加载 arm64 的原生库)。
- 新增 SevenZipNativePlatform,仅在 Linux + aarch64 时调用
SevenZip.initSevenZipFromPlatformJAR("Linux-arm64");其它平台不做任何处理。
初始化失败只记录日志,不影响应用启动。
- CompressFileReader 在静态初始化块中调用,解压逻辑不变。
新增 SevenZipNativePlatformTests 4 条。
Signed-off-by: yuhaibo <yuhaibo@hotmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
在 aarch64 的 Linux 上预览任何压缩包(zip、rar、7z 等),页面提示:
日志:
调用栈在
CompressFileReader.unRar→SevenZip.openInArchive。x86_64 的 Linux 与 Windows 上正常。5.0.3(即当前 master)可以复现。原因
有两处,只解决其中一处都不行:
1. 原生库不在。
server/pom.xml依赖的sevenzipjbinding-all-platforms(16.02-2.01)里只有Linux-amd64、Linux-i386、Mac-x86_64、Windows-amd64、Windows-x86五个平台的原生库,没有 Linux arm64。Maven Central 上同版本另有一个单独的构件net.sf.sevenzipjbinding:sevenzipjbinding-linux-arm64:16.02-2.01,里面是Linux-arm64/lib7-Zip-JBinding.so。2. 只加依赖,SevenZipJBinding 仍然选不到它。
SevenZip.getPlatformBestMatch的选法是:平台列表只有一项就用那一项;否则用os.name的第一个单词 +-+os.arch去列表里找完全相同的名字。JVM 在这种机器上的os.arch是aarch64,拼出来是Linux-aarch64,而原生库所在的目录、平台列表里登记的名字都是Linux-arm64,匹配不上。另外两个 jar 各带一份同名的
/sevenzipjbinding-platforms.properties,SevenZipJBinding 只读取类路径上的第一份:如果 arm64 的 jar 排在前面,平台列表只剩Linux-arm64一项,x86_64 与 Windows 上也会去加载 arm64 的原生库。所以也不能靠调整依赖顺序来解决。修复
server/pom.xml:引入sevenzipjbinding-linux-arm64(沿用${sevenzipjbinding.version}),放在sevenzipjbinding-all-platforms之后,其它平台读到的平台列表与原来相同;cn.keking.utils.SevenZipNativePlatform:只在os.name第一个单词是Linux且os.arch是aarch64时,调用SevenZip.initSevenZipFromPlatformJAR("Linux-arm64")显式指定平台名;其它平台直接返回,仍由 SevenZipJBinding 自动选择。初始化失败只记录日志、不向外抛,不影响应用启动(之后真正解压时 SevenZipJBinding 会按原来的方式报错);CompressFileReader:增加静态初始化块调用SevenZipNativePlatform.init()。解压逻辑没有改动。没有直接升级到 sevenzipjbinding
23.01-2.2(它的 all-platforms 自带Linux-arm64):那样 x86_64 与 Windows 上的解压引擎也会一起从 16.02 换成 23.01,all-platforms 的 jar 也从约 7 MB 变成约 24 MB,影响范围比修这个问题大得多,更适合单独评估。本 PR 只增加一个约 2 MB 的 jar,其它平台使用的原生库一个字节都不变。如果维护者更倾向于直接升级版本,我可以改成那种做法。验证
新增
SevenZipNativePlatformTests,4 条。运行测试的机器通常不是 arm64,无法真正加载该原生库,所以校验的是加载之前的各个环节:shouldShipLinuxArm64NativeLibrary:Linux-arm64的原生库在类路径上,并且是 AArch64 的 ELF 文件;shouldSelectLinuxArm64PlatformOnLinuxAarch64:Linux + aarch64 时指定的平台名是Linux-arm64,按这个名字能取到原生库;shouldLeaveOtherPlatformsToAutomaticSelection:其它平台(Linux amd64 / i386 / arm、Windows、macOS)不指定平台名;shouldKeepExistingPlatformsAvailable:原有平台仍在 SevenZipJBinding 读到的平台列表里,原生库仍能取到。修改前先跑(只放测试与一个空实现):第 1、2 条失败(
/Linux-arm64/sevenzipjbinding-lib.properties is not on the classpath、expected: <Linux-arm64> but was: <null>);修改后 4 条全部通过。把平台名的指定去掉,第 2 条重新失败;把两个依赖的顺序对调,第 4 条失败(listed platforms: [Linux-arm64])。mvn -B -pl server test -Dtest='!ServerMainTests'(Windows,JDK 25):Tests run: 91, Failures: 0, Errors: 1。唯一的 1 条是ArchiveDirectorySecurityTests.cachedArchivePreviewRendersItsTreeWithoutAnEnumerationRequest,它要创建文件名带双引号的文件,Windows 不允许,在未修改的 master 上同样失败(master 为 87 条、同样 1 条 Error),与本次修改无关。实际环境:已在 aarch64 的 Linux(容器部署,JDK 25)上用与本 PR 相同的改动(只有注释与日志文案不同)验证——修改前预览压缩包失败并出现上面的日志;修改后 zip 能列出文件树,包内的文件能打开,日志中出现原生库按
Linux-arm64平台加载成功的那一行。x86_64 的 Linux 上压缩包预览照常。适用范围
glibc 的 Linux arm64。musl(如 Alpine)与 32 位 ARM 不在本 PR 范围内,
16.02-2.01没有对应的原生库。