案例一
2025年12月18日,发现v1.0.3版本桌面端安装包体积爆炸增大,从原本的150MB左右暴涨到1GB,如下图所示。
由于三端均产生该问题,以 macOS 端(.dmg)为例展开排查。解包产物,切入 contents 目录查看文件夹大小,执行 du -sh ./*,结果如下:
1 | 116K ./Contents/_CodeSignature |
显然 Contents/app(999MB) 炸了。这也就是说:这次膨胀原因主要来自 应用层打包进去的 jar/依赖/资源 异常地多,初步怀疑是某个库发生了问题,将三份native包全都打包到一个native平台上了。
切入 Contents/app 执行 du -sh ./* ,结果如下:
1 | ... |
这就很显然了,验证了猜想是对的。明明是macOS平台的包,却连 windows 及 linux 的jar都被打包进来,所以导致了包体积暴涨。下一步是排查最终的罪魁祸首,是谁干了这件蠢事。回到项目中运行 ./gradlew :composeApp:dependencyInsight --configuration desktopRuntimeClasspath --dependency javacv-platform,输出如下:

水落石出,结果显示是 cmp-image-pick-n-crop-jvm:1.1.2 这个库依赖 org.bytedeco:javacv-platform:1.5.8 又依赖 org.bytedeco:opencv-platform:4.6.0-1.5.8。cmp-image-pick-n-crop 是我在Github上找的一个用来裁剪图片的第三方库,它的JVM平台包依赖了 *-platform 全家桶,导致暴增。我在本次更新的改动中将其版本从 1.1.1 升级到 1.1.2 才出现这个问题,看来是作者在更新他的库依赖时犯了个低级错误。
修复很简单,回退到 1.1.1 即可解决,但是治标不治本。本着开源精神至上的原则我把该库fork并拉了下来准备直接修并提PR,结果这才发现这是个假开源项目。源代码是空的,只有个示例app。对印度人的刻板印象再次加深。无奈只好提了个issue作罢,但估计也不会被理睬,看commit日期这个库已经被放弃维护了,令人感叹。
案例二
2026年1月28日,发现v1.0.4版本桌面端安装包体积再次出现异常增大,但这次涨幅不如上次,且只有 Win / Linux 平台受影响。

这次以 Linux 平台 (.deb) 为例进行排查,还是老方法,解包然后看谁变大了。分别对新老版本安装包运行 du -h -d 4 old | sort -h | tail -n 30 查看:
1 | # old |
lib/runtime 炸了,显然这次不是依赖包的问题,而是JRE出了差错,就像没被裁剪一样。在新版本包中运行 find new/opt/bandoristationm/lib/runtime/lib -type f -print0 | xargs -0 ls -lnS | head -n 30,结果如下:
1 | -rw-r--r-- 1 501 20 209861688 Jan 28 17:05 new/opt/bandoristationm/lib/runtime/lib/libcef.so |
一上来就看懂了,怎么混进来个庞然大物 libcef.so,我这是不知道被谁塞了整套 Chromium 啊。翻了翻过去的 commit 记录,定位了罪魁祸首:在 Android Studio 建议迁移 gradle 后,gradle 在升级到9.0.0的同时,顺手给我塞了个 gradle-daemon-jvm.properties。我没有在意,但是这个配置文件里面设置了 toolchainVendor=JETBRAINS,即指定 JBR 为 Gradle Daemon 的运行时,而上面的URL里面又指定了 JBR 的版本是带 JCEF 的版本:
- Linux:
jbrsdk_jcef-21.0.9-linux-x64-b895.149.tar.gz - Windows:
jbrsdk_jcef-21.0.9-windows-x64-b895.149.zip - macOS:
jbrsdk_jcef-21.0.9-osx-aarch64-b895.149.tar.gz
这也导致当workflow在跑时,Gradle构建时,不会再用我指定的 temurin,而是现场下带JCEF 的 JBR 用,自然打包时把 libcef.so 等一系列不需要的东西也拐进来了。
解决:直接rollback即可。
经验总结
遇到包体积暴涨不用慌,凡事皆有迹可循。桌面端打包(Compose Desktop/jpackage)有个特点:最终体积主要由两部分决定:
- 应用层:
lib/app(jar、资源、代码)-> 通常增长是渐进的 - 运行时层:
lib/runtime(JRE/JBR、native、资源包)-> 一旦策略变了就是断崖式增长
不要用“总大小”当指标,而是要抓“结构”,把体积拆成可解释的结构指标,迅速归因:
app变大 → 依赖/资源/重复打包runtime变大 → JDK/JBR 变更、jlink 失效、引入 JCEF、debug 符号等